Initial commit
This commit is contained in:
commit
a6272848f9
379 changed files with 74829 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
993
build/dev/javascript/gleam_stdlib/dict.mjs
Normal file
993
build/dev/javascript/gleam_stdlib/dict.mjs
Normal file
|
|
@ -0,0 +1,993 @@
|
|||
/**
|
||||
* This file uses jsdoc to annotate types.
|
||||
* These types can be checked using the typescript compiler with "checkjs" option.
|
||||
*/
|
||||
|
||||
import { isEqual } from "./gleam.mjs";
|
||||
|
||||
const referenceMap = /* @__PURE__ */ new WeakMap();
|
||||
const tempDataView = /* @__PURE__ */ new DataView(
|
||||
/* @__PURE__ */ new ArrayBuffer(8),
|
||||
);
|
||||
let referenceUID = 0;
|
||||
/**
|
||||
* hash the object by reference using a weak map and incrementing uid
|
||||
* @param {any} o
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashByReference(o) {
|
||||
const known = referenceMap.get(o);
|
||||
if (known !== undefined) {
|
||||
return known;
|
||||
}
|
||||
const hash = referenceUID++;
|
||||
if (referenceUID === 0x7fffffff) {
|
||||
referenceUID = 0;
|
||||
}
|
||||
referenceMap.set(o, hash);
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* merge two hashes in an order sensitive way
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashMerge(a, b) {
|
||||
return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* standard string hash popularised by java
|
||||
* @param {string} s
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashString(s) {
|
||||
let hash = 0;
|
||||
const len = s.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
hash = (Math.imul(31, hash) + s.charCodeAt(i)) | 0;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash a number by converting to two integers and do some jumbling
|
||||
* @param {number} n
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashNumber(n) {
|
||||
tempDataView.setFloat64(0, n);
|
||||
const i = tempDataView.getInt32(0);
|
||||
const j = tempDataView.getInt32(4);
|
||||
return Math.imul(0x45d9f3b, (i >> 16) ^ i) ^ j;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash a BigInt by converting it to a string and hashing that
|
||||
* @param {BigInt} n
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashBigInt(n) {
|
||||
return hashString(n.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* hash any js object
|
||||
* @param {any} o
|
||||
* @returns {number}
|
||||
*/
|
||||
function hashObject(o) {
|
||||
const proto = Object.getPrototypeOf(o);
|
||||
if (proto !== null && typeof proto.hashCode === "function") {
|
||||
try {
|
||||
const code = o.hashCode(o);
|
||||
if (typeof code === "number") {
|
||||
return code;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) {
|
||||
return hashByReference(o);
|
||||
}
|
||||
if (o instanceof Date) {
|
||||
return hashNumber(o.getTime());
|
||||
}
|
||||
let h = 0;
|
||||
if (o instanceof ArrayBuffer) {
|
||||
o = new Uint8Array(o);
|
||||
}
|
||||
if (Array.isArray(o) || o instanceof Uint8Array) {
|
||||
for (let i = 0; i < o.length; i++) {
|
||||
h = (Math.imul(31, h) + getHash(o[i])) | 0;
|
||||
}
|
||||
} else if (o instanceof Set) {
|
||||
o.forEach((v) => {
|
||||
h = (h + getHash(v)) | 0;
|
||||
});
|
||||
} else if (o instanceof Map) {
|
||||
o.forEach((v, k) => {
|
||||
h = (h + hashMerge(getHash(v), getHash(k))) | 0;
|
||||
});
|
||||
} else {
|
||||
const keys = Object.keys(o);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i];
|
||||
const v = o[k];
|
||||
h = (h + hashMerge(getHash(v), hashString(k))) | 0;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash any js value
|
||||
* @param {any} u
|
||||
* @returns {number}
|
||||
*/
|
||||
export function getHash(u) {
|
||||
if (u === null) return 0x42108422;
|
||||
if (u === undefined) return 0x42108423;
|
||||
if (u === true) return 0x42108421;
|
||||
if (u === false) return 0x42108420;
|
||||
switch (typeof u) {
|
||||
case "number":
|
||||
return hashNumber(u);
|
||||
case "string":
|
||||
return hashString(u);
|
||||
case "bigint":
|
||||
return hashBigInt(u);
|
||||
case "object":
|
||||
return hashObject(u);
|
||||
case "symbol":
|
||||
return hashByReference(u);
|
||||
case "function":
|
||||
return hashByReference(u);
|
||||
default:
|
||||
return 0; // should be unreachable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @template K,V
|
||||
* @typedef {ArrayNode<K,V> | IndexNode<K,V> | CollisionNode<K,V>} Node
|
||||
*/
|
||||
/**
|
||||
* @template K,V
|
||||
* @typedef {{ type: typeof ENTRY, k: K, v: V }} Entry
|
||||
*/
|
||||
/**
|
||||
* @template K,V
|
||||
* @typedef {{ type: typeof ARRAY_NODE, size: number, array: (undefined | Entry<K,V> | Node<K,V>)[] }} ArrayNode
|
||||
*/
|
||||
/**
|
||||
* @template K,V
|
||||
* @typedef {{ type: typeof INDEX_NODE, bitmap: number, array: (Entry<K,V> | Node<K,V>)[] }} IndexNode
|
||||
*/
|
||||
/**
|
||||
* @template K,V
|
||||
* @typedef {{ type: typeof COLLISION_NODE, hash: number, array: Entry<K, V>[] }} CollisionNode
|
||||
*/
|
||||
/**
|
||||
* @typedef {{ val: boolean }} Flag
|
||||
*/
|
||||
const SHIFT = 5; // number of bits you need to shift by to get the next bucket
|
||||
const BUCKET_SIZE = Math.pow(2, SHIFT);
|
||||
const MASK = BUCKET_SIZE - 1; // used to zero out all bits not in the bucket
|
||||
const MAX_INDEX_NODE = BUCKET_SIZE / 2; // when does index node grow into array node
|
||||
const MIN_ARRAY_NODE = BUCKET_SIZE / 4; // when does array node shrink to index node
|
||||
const ENTRY = 0;
|
||||
const ARRAY_NODE = 1;
|
||||
const INDEX_NODE = 2;
|
||||
const COLLISION_NODE = 3;
|
||||
|
||||
/** @type {IndexNode<any,any>} */
|
||||
const EMPTY = {
|
||||
type: INDEX_NODE,
|
||||
bitmap: 0,
|
||||
array: [],
|
||||
};
|
||||
/**
|
||||
* Mask the hash to get only the bucket corresponding to shift
|
||||
* @param {number} hash
|
||||
* @param {number} shift
|
||||
* @returns {number}
|
||||
*/
|
||||
function mask(hash, shift) {
|
||||
return (hash >>> shift) & MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set only the Nth bit where N is the masked hash
|
||||
* @param {number} hash
|
||||
* @param {number} shift
|
||||
* @returns {number}
|
||||
*/
|
||||
function bitpos(hash, shift) {
|
||||
return 1 << mask(hash, shift);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of 1 bits in a number
|
||||
* @param {number} x
|
||||
* @returns {number}
|
||||
*/
|
||||
function bitcount(x) {
|
||||
x -= (x >> 1) & 0x55555555;
|
||||
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
|
||||
x = (x + (x >> 4)) & 0x0f0f0f0f;
|
||||
x += x >> 8;
|
||||
x += x >> 16;
|
||||
return x & 0x7f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the array index of an item in a bitmap index node
|
||||
* @param {number} bitmap
|
||||
* @param {number} bit
|
||||
* @returns {number}
|
||||
*/
|
||||
function index(bitmap, bit) {
|
||||
return bitcount(bitmap & (bit - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Efficiently copy an array and set one value at an index
|
||||
* @template T
|
||||
* @param {T[]} arr
|
||||
* @param {number} at
|
||||
* @param {T} val
|
||||
* @returns {T[]}
|
||||
*/
|
||||
function cloneAndSet(arr, at, val) {
|
||||
const len = arr.length;
|
||||
const out = new Array(len);
|
||||
for (let i = 0; i < len; ++i) {
|
||||
out[i] = arr[i];
|
||||
}
|
||||
out[at] = val;
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Efficiently copy an array and insert one value at an index
|
||||
* @template T
|
||||
* @param {T[]} arr
|
||||
* @param {number} at
|
||||
* @param {T} val
|
||||
* @returns {T[]}
|
||||
*/
|
||||
function spliceIn(arr, at, val) {
|
||||
const len = arr.length;
|
||||
const out = new Array(len + 1);
|
||||
let i = 0;
|
||||
let g = 0;
|
||||
while (i < at) {
|
||||
out[g++] = arr[i++];
|
||||
}
|
||||
out[g++] = val;
|
||||
while (i < len) {
|
||||
out[g++] = arr[i++];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Efficiently copy an array and remove one value at an index
|
||||
* @template T
|
||||
* @param {T[]} arr
|
||||
* @param {number} at
|
||||
* @returns {T[]}
|
||||
*/
|
||||
function spliceOut(arr, at) {
|
||||
const len = arr.length;
|
||||
const out = new Array(len - 1);
|
||||
let i = 0;
|
||||
let g = 0;
|
||||
while (i < at) {
|
||||
out[g++] = arr[i++];
|
||||
}
|
||||
++i;
|
||||
while (i < len) {
|
||||
out[g++] = arr[i++];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node containing two entries
|
||||
* @template K,V
|
||||
* @param {number} shift
|
||||
* @param {K} key1
|
||||
* @param {V} val1
|
||||
* @param {number} key2hash
|
||||
* @param {K} key2
|
||||
* @param {V} val2
|
||||
* @returns {Node<K,V>}
|
||||
*/
|
||||
function createNode(shift, key1, val1, key2hash, key2, val2) {
|
||||
const key1hash = getHash(key1);
|
||||
if (key1hash === key2hash) {
|
||||
return {
|
||||
type: COLLISION_NODE,
|
||||
hash: key1hash,
|
||||
array: [
|
||||
{ type: ENTRY, k: key1, v: val1 },
|
||||
{ type: ENTRY, k: key2, v: val2 },
|
||||
],
|
||||
};
|
||||
}
|
||||
const addedLeaf = { val: false };
|
||||
return assoc(
|
||||
assocIndex(EMPTY, shift, key1hash, key1, val1, addedLeaf),
|
||||
shift,
|
||||
key2hash,
|
||||
key2,
|
||||
val2,
|
||||
addedLeaf,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @callback AssocFunction
|
||||
* @param {T} root
|
||||
* @param {number} shift
|
||||
* @param {number} hash
|
||||
* @param {K} key
|
||||
* @param {V} val
|
||||
* @param {Flag} addedLeaf
|
||||
* @returns {Node<K,V>}
|
||||
*/
|
||||
/**
|
||||
* Associate a node with a new entry, creating a new node
|
||||
* @template T,K,V
|
||||
* @type {AssocFunction<Node<K,V>,K,V>}
|
||||
*/
|
||||
function assoc(root, shift, hash, key, val, addedLeaf) {
|
||||
switch (root.type) {
|
||||
case ARRAY_NODE:
|
||||
return assocArray(root, shift, hash, key, val, addedLeaf);
|
||||
case INDEX_NODE:
|
||||
return assocIndex(root, shift, hash, key, val, addedLeaf);
|
||||
case COLLISION_NODE:
|
||||
return assocCollision(root, shift, hash, key, val, addedLeaf);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @type {AssocFunction<ArrayNode<K,V>,K,V>}
|
||||
*/
|
||||
function assocArray(root, shift, hash, key, val, addedLeaf) {
|
||||
const idx = mask(hash, shift);
|
||||
const node = root.array[idx];
|
||||
// if the corresponding index is empty set the index to a newly created node
|
||||
if (node === undefined) {
|
||||
addedLeaf.val = true;
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size + 1,
|
||||
array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }),
|
||||
};
|
||||
}
|
||||
if (node.type === ENTRY) {
|
||||
// if keys are equal replace the entry
|
||||
if (isEqual(key, node.k)) {
|
||||
if (val === node.v) {
|
||||
return root;
|
||||
}
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size,
|
||||
array: cloneAndSet(root.array, idx, {
|
||||
type: ENTRY,
|
||||
k: key,
|
||||
v: val,
|
||||
}),
|
||||
};
|
||||
}
|
||||
// otherwise upgrade the entry to a node and insert
|
||||
addedLeaf.val = true;
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size,
|
||||
array: cloneAndSet(
|
||||
root.array,
|
||||
idx,
|
||||
createNode(shift + SHIFT, node.k, node.v, hash, key, val),
|
||||
),
|
||||
};
|
||||
}
|
||||
// otherwise call assoc on the child node
|
||||
const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf);
|
||||
// if the child node hasn't changed just return the old root
|
||||
if (n === node) {
|
||||
return root;
|
||||
}
|
||||
// otherwise set the index to the new node
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size,
|
||||
array: cloneAndSet(root.array, idx, n),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @type {AssocFunction<IndexNode<K,V>,K,V>}
|
||||
*/
|
||||
function assocIndex(root, shift, hash, key, val, addedLeaf) {
|
||||
const bit = bitpos(hash, shift);
|
||||
const idx = index(root.bitmap, bit);
|
||||
// if there is already a item at this hash index..
|
||||
if ((root.bitmap & bit) !== 0) {
|
||||
// if there is a node at the index (not an entry), call assoc on the child node
|
||||
const node = root.array[idx];
|
||||
if (node.type !== ENTRY) {
|
||||
const n = assoc(node, shift + SHIFT, hash, key, val, addedLeaf);
|
||||
if (n === node) {
|
||||
return root;
|
||||
}
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap,
|
||||
array: cloneAndSet(root.array, idx, n),
|
||||
};
|
||||
}
|
||||
// otherwise there is an entry at the index
|
||||
// if the keys are equal replace the entry with the updated value
|
||||
const nodeKey = node.k;
|
||||
if (isEqual(key, nodeKey)) {
|
||||
if (val === node.v) {
|
||||
return root;
|
||||
}
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap,
|
||||
array: cloneAndSet(root.array, idx, {
|
||||
type: ENTRY,
|
||||
k: key,
|
||||
v: val,
|
||||
}),
|
||||
};
|
||||
}
|
||||
// if the keys are not equal, replace the entry with a new child node
|
||||
addedLeaf.val = true;
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap,
|
||||
array: cloneAndSet(
|
||||
root.array,
|
||||
idx,
|
||||
createNode(shift + SHIFT, nodeKey, node.v, hash, key, val),
|
||||
),
|
||||
};
|
||||
} else {
|
||||
// else there is currently no item at the hash index
|
||||
const n = root.array.length;
|
||||
// if the number of nodes is at the maximum, expand this node into an array node
|
||||
if (n >= MAX_INDEX_NODE) {
|
||||
// create a 32 length array for the new array node (one for each bit in the hash)
|
||||
const nodes = new Array(32);
|
||||
// create and insert a node for the new entry
|
||||
const jdx = mask(hash, shift);
|
||||
nodes[jdx] = assocIndex(EMPTY, shift + SHIFT, hash, key, val, addedLeaf);
|
||||
let j = 0;
|
||||
let bitmap = root.bitmap;
|
||||
// place each item in the index node into the correct spot in the array node
|
||||
// loop through all 32 bits / array positions
|
||||
for (let i = 0; i < 32; i++) {
|
||||
if ((bitmap & 1) !== 0) {
|
||||
const node = root.array[j++];
|
||||
nodes[i] = node;
|
||||
}
|
||||
// shift the bitmap to process the next bit
|
||||
bitmap = bitmap >>> 1;
|
||||
}
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: n + 1,
|
||||
array: nodes,
|
||||
};
|
||||
} else {
|
||||
// else there is still space in this index node
|
||||
// simply insert a new entry at the hash index
|
||||
const newArray = spliceIn(root.array, idx, {
|
||||
type: ENTRY,
|
||||
k: key,
|
||||
v: val,
|
||||
});
|
||||
addedLeaf.val = true;
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap | bit,
|
||||
array: newArray,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @type {AssocFunction<CollisionNode<K,V>,K,V>}
|
||||
*/
|
||||
function assocCollision(root, shift, hash, key, val, addedLeaf) {
|
||||
// if there is a hash collision
|
||||
if (hash === root.hash) {
|
||||
const idx = collisionIndexOf(root, key);
|
||||
// if this key already exists replace the entry with the new value
|
||||
if (idx !== -1) {
|
||||
const entry = root.array[idx];
|
||||
if (entry.v === val) {
|
||||
return root;
|
||||
}
|
||||
return {
|
||||
type: COLLISION_NODE,
|
||||
hash: hash,
|
||||
array: cloneAndSet(root.array, idx, { type: ENTRY, k: key, v: val }),
|
||||
};
|
||||
}
|
||||
// otherwise insert the entry at the end of the array
|
||||
const size = root.array.length;
|
||||
addedLeaf.val = true;
|
||||
return {
|
||||
type: COLLISION_NODE,
|
||||
hash: hash,
|
||||
array: cloneAndSet(root.array, size, { type: ENTRY, k: key, v: val }),
|
||||
};
|
||||
}
|
||||
// if there is no hash collision, upgrade to an index node
|
||||
return assoc(
|
||||
{
|
||||
type: INDEX_NODE,
|
||||
bitmap: bitpos(root.hash, shift),
|
||||
array: [root],
|
||||
},
|
||||
shift,
|
||||
hash,
|
||||
key,
|
||||
val,
|
||||
addedLeaf,
|
||||
);
|
||||
}
|
||||
/**
|
||||
* Find the index of a key in the collision node's array
|
||||
* @template K,V
|
||||
* @param {CollisionNode<K,V>} root
|
||||
* @param {K} key
|
||||
* @returns {number}
|
||||
*/
|
||||
function collisionIndexOf(root, key) {
|
||||
const size = root.array.length;
|
||||
for (let i = 0; i < size; i++) {
|
||||
if (isEqual(key, root.array[i].k)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @callback FindFunction
|
||||
* @param {T} root
|
||||
* @param {number} shift
|
||||
* @param {number} hash
|
||||
* @param {K} key
|
||||
* @returns {undefined | Entry<K,V>}
|
||||
*/
|
||||
/**
|
||||
* Return the found entry or undefined if not present in the root
|
||||
* @template K,V
|
||||
* @type {FindFunction<Node<K,V>,K,V>}
|
||||
*/
|
||||
function find(root, shift, hash, key) {
|
||||
switch (root.type) {
|
||||
case ARRAY_NODE:
|
||||
return findArray(root, shift, hash, key);
|
||||
case INDEX_NODE:
|
||||
return findIndex(root, shift, hash, key);
|
||||
case COLLISION_NODE:
|
||||
return findCollision(root, key);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @type {FindFunction<ArrayNode<K,V>,K,V>}
|
||||
*/
|
||||
function findArray(root, shift, hash, key) {
|
||||
const idx = mask(hash, shift);
|
||||
const node = root.array[idx];
|
||||
if (node === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (node.type !== ENTRY) {
|
||||
return find(node, shift + SHIFT, hash, key);
|
||||
}
|
||||
if (isEqual(key, node.k)) {
|
||||
return node;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @type {FindFunction<IndexNode<K,V>,K,V>}
|
||||
*/
|
||||
function findIndex(root, shift, hash, key) {
|
||||
const bit = bitpos(hash, shift);
|
||||
if ((root.bitmap & bit) === 0) {
|
||||
return undefined;
|
||||
}
|
||||
const idx = index(root.bitmap, bit);
|
||||
const node = root.array[idx];
|
||||
if (node.type !== ENTRY) {
|
||||
return find(node, shift + SHIFT, hash, key);
|
||||
}
|
||||
if (isEqual(key, node.k)) {
|
||||
return node;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @param {CollisionNode<K,V>} root
|
||||
* @param {K} key
|
||||
* @returns {undefined | Entry<K,V>}
|
||||
*/
|
||||
function findCollision(root, key) {
|
||||
const idx = collisionIndexOf(root, key);
|
||||
if (idx < 0) {
|
||||
return undefined;
|
||||
}
|
||||
return root.array[idx];
|
||||
}
|
||||
/**
|
||||
* @template T,K,V
|
||||
* @callback WithoutFunction
|
||||
* @param {T} root
|
||||
* @param {number} shift
|
||||
* @param {number} hash
|
||||
* @param {K} key
|
||||
* @returns {undefined | Node<K,V>}
|
||||
*/
|
||||
/**
|
||||
* Remove an entry from the root, returning the updated root.
|
||||
* Returns undefined if the node should be removed from the parent.
|
||||
* @template K,V
|
||||
* @type {WithoutFunction<Node<K,V>,K,V>}
|
||||
* */
|
||||
function without(root, shift, hash, key) {
|
||||
switch (root.type) {
|
||||
case ARRAY_NODE:
|
||||
return withoutArray(root, shift, hash, key);
|
||||
case INDEX_NODE:
|
||||
return withoutIndex(root, shift, hash, key);
|
||||
case COLLISION_NODE:
|
||||
return withoutCollision(root, key);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @type {WithoutFunction<ArrayNode<K,V>,K,V>}
|
||||
*/
|
||||
function withoutArray(root, shift, hash, key) {
|
||||
const idx = mask(hash, shift);
|
||||
const node = root.array[idx];
|
||||
if (node === undefined) {
|
||||
return root; // already empty
|
||||
}
|
||||
let n = undefined;
|
||||
// if node is an entry and the keys are not equal there is nothing to remove
|
||||
// if node is not an entry do a recursive call
|
||||
if (node.type === ENTRY) {
|
||||
if (!isEqual(node.k, key)) {
|
||||
return root; // no changes
|
||||
}
|
||||
} else {
|
||||
n = without(node, shift + SHIFT, hash, key);
|
||||
if (n === node) {
|
||||
return root; // no changes
|
||||
}
|
||||
}
|
||||
// if the recursive call returned undefined the node should be removed
|
||||
if (n === undefined) {
|
||||
// if the number of child nodes is at the minimum, pack into an index node
|
||||
if (root.size <= MIN_ARRAY_NODE) {
|
||||
const arr = root.array;
|
||||
const out = new Array(root.size - 1);
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
let bitmap = 0;
|
||||
while (i < idx) {
|
||||
const nv = arr[i];
|
||||
if (nv !== undefined) {
|
||||
out[j] = nv;
|
||||
bitmap |= 1 << i;
|
||||
++j;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
++i; // skip copying the removed node
|
||||
while (i < arr.length) {
|
||||
const nv = arr[i];
|
||||
if (nv !== undefined) {
|
||||
out[j] = nv;
|
||||
bitmap |= 1 << i;
|
||||
++j;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: bitmap,
|
||||
array: out,
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size - 1,
|
||||
array: cloneAndSet(root.array, idx, n),
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: ARRAY_NODE,
|
||||
size: root.size,
|
||||
array: cloneAndSet(root.array, idx, n),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @type {WithoutFunction<IndexNode<K,V>,K,V>}
|
||||
*/
|
||||
function withoutIndex(root, shift, hash, key) {
|
||||
const bit = bitpos(hash, shift);
|
||||
if ((root.bitmap & bit) === 0) {
|
||||
return root; // already empty
|
||||
}
|
||||
const idx = index(root.bitmap, bit);
|
||||
const node = root.array[idx];
|
||||
// if the item is not an entry
|
||||
if (node.type !== ENTRY) {
|
||||
const n = without(node, shift + SHIFT, hash, key);
|
||||
if (n === node) {
|
||||
return root; // no changes
|
||||
}
|
||||
// if not undefined, the child node still has items, so update it
|
||||
if (n !== undefined) {
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap,
|
||||
array: cloneAndSet(root.array, idx, n),
|
||||
};
|
||||
}
|
||||
// otherwise the child node should be removed
|
||||
// if it was the only child node, remove this node from the parent
|
||||
if (root.bitmap === bit) {
|
||||
return undefined;
|
||||
}
|
||||
// otherwise just remove the child node
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap ^ bit,
|
||||
array: spliceOut(root.array, idx),
|
||||
};
|
||||
}
|
||||
// otherwise the item is an entry, remove it if the key matches
|
||||
if (isEqual(key, node.k)) {
|
||||
if (root.bitmap === bit) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
type: INDEX_NODE,
|
||||
bitmap: root.bitmap ^ bit,
|
||||
array: spliceOut(root.array, idx),
|
||||
};
|
||||
}
|
||||
return root;
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @param {CollisionNode<K,V>} root
|
||||
* @param {K} key
|
||||
* @returns {undefined | Node<K,V>}
|
||||
*/
|
||||
function withoutCollision(root, key) {
|
||||
const idx = collisionIndexOf(root, key);
|
||||
// if the key not found, no changes
|
||||
if (idx < 0) {
|
||||
return root;
|
||||
}
|
||||
// otherwise the entry was found, remove it
|
||||
// if it was the only entry in this node, remove the whole node
|
||||
if (root.array.length === 1) {
|
||||
return undefined;
|
||||
}
|
||||
// otherwise just remove the entry
|
||||
return {
|
||||
type: COLLISION_NODE,
|
||||
hash: root.hash,
|
||||
array: spliceOut(root.array, idx),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* @template K,V
|
||||
* @param {undefined | Node<K,V>} root
|
||||
* @param {(value:V,key:K)=>void} fn
|
||||
* @returns {void}
|
||||
*/
|
||||
function forEach(root, fn) {
|
||||
if (root === undefined) {
|
||||
return;
|
||||
}
|
||||
const items = root.array;
|
||||
const size = items.length;
|
||||
for (let i = 0; i < size; i++) {
|
||||
const item = items[i];
|
||||
if (item === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (item.type === ENTRY) {
|
||||
fn(item.v, item.k);
|
||||
continue;
|
||||
}
|
||||
forEach(item, fn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra wrapper to keep track of Dict size and clean up the API
|
||||
* @template K,V
|
||||
*/
|
||||
export default class Dict {
|
||||
/**
|
||||
* @template V
|
||||
* @param {Record<string,V>} o
|
||||
* @returns {Dict<string,V>}
|
||||
*/
|
||||
static fromObject(o) {
|
||||
const keys = Object.keys(o);
|
||||
/** @type Dict<string,V> */
|
||||
let m = Dict.new();
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i];
|
||||
m = m.set(k, o[k]);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* @template K,V
|
||||
* @param {Map<K,V>} o
|
||||
* @returns {Dict<K,V>}
|
||||
*/
|
||||
static fromMap(o) {
|
||||
/** @type Dict<K,V> */
|
||||
let m = Dict.new();
|
||||
o.forEach((v, k) => {
|
||||
m = m.set(k, v);
|
||||
});
|
||||
return m;
|
||||
}
|
||||
|
||||
static new() {
|
||||
return new Dict(undefined, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {undefined | Node<K,V>} root
|
||||
* @param {number} size
|
||||
*/
|
||||
constructor(root, size) {
|
||||
this.root = root;
|
||||
this.size = size;
|
||||
}
|
||||
/**
|
||||
* @template NotFound
|
||||
* @param {K} key
|
||||
* @param {NotFound} notFound
|
||||
* @returns {NotFound | V}
|
||||
*/
|
||||
get(key, notFound) {
|
||||
if (this.root === undefined) {
|
||||
return notFound;
|
||||
}
|
||||
const found = find(this.root, 0, getHash(key), key);
|
||||
if (found === undefined) {
|
||||
return notFound;
|
||||
}
|
||||
return found.v;
|
||||
}
|
||||
/**
|
||||
* @param {K} key
|
||||
* @param {V} val
|
||||
* @returns {Dict<K,V>}
|
||||
*/
|
||||
set(key, val) {
|
||||
const addedLeaf = { val: false };
|
||||
const root = this.root === undefined ? EMPTY : this.root;
|
||||
const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf);
|
||||
if (newRoot === this.root) {
|
||||
return this;
|
||||
}
|
||||
return new Dict(newRoot, addedLeaf.val ? this.size + 1 : this.size);
|
||||
}
|
||||
/**
|
||||
* @param {K} key
|
||||
* @returns {Dict<K,V>}
|
||||
*/
|
||||
delete(key) {
|
||||
if (this.root === undefined) {
|
||||
return this;
|
||||
}
|
||||
const newRoot = without(this.root, 0, getHash(key), key);
|
||||
if (newRoot === this.root) {
|
||||
return this;
|
||||
}
|
||||
if (newRoot === undefined) {
|
||||
return Dict.new();
|
||||
}
|
||||
return new Dict(newRoot, this.size - 1);
|
||||
}
|
||||
/**
|
||||
* @param {K} key
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(key) {
|
||||
if (this.root === undefined) {
|
||||
return false;
|
||||
}
|
||||
return find(this.root, 0, getHash(key), key) !== undefined;
|
||||
}
|
||||
/**
|
||||
* @returns {[K,V][]}
|
||||
*/
|
||||
entries() {
|
||||
if (this.root === undefined) {
|
||||
return [];
|
||||
}
|
||||
/** @type [K,V][] */
|
||||
const result = [];
|
||||
this.forEach((v, k) => result.push([k, v]));
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {(val:V,key:K)=>void} fn
|
||||
*/
|
||||
forEach(fn) {
|
||||
forEach(this.root, fn);
|
||||
}
|
||||
hashCode() {
|
||||
let h = 0;
|
||||
this.forEach((v, k) => {
|
||||
h = (h + hashMerge(getHash(v), getHash(k))) | 0;
|
||||
});
|
||||
return h;
|
||||
}
|
||||
/**
|
||||
* @param {unknown} o
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(o) {
|
||||
if (!(o instanceof Dict) || this.size !== o.size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
this.forEach((v, k) => {
|
||||
if (!isEqual(o.get(k, !v), v)) {
|
||||
throw unequalDictSymbol;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (e === unequalDictSymbol) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is thrown internally in Dict.equals() so that it returns false as soon
|
||||
// as a non-matching key is found
|
||||
const unequalDictSymbol = /* @__PURE__ */ Symbol();
|
||||
1
build/dev/javascript/gleam_stdlib/gleam.mjs
Normal file
1
build/dev/javascript/gleam_stdlib/gleam.mjs
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from "../prelude.mjs";
|
||||
285
build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs
Normal file
285
build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs
Normal file
|
|
@ -0,0 +1,285 @@
|
|||
import { Ok, toList, bitArraySlice, bitArraySliceToInt } from "../gleam.mjs";
|
||||
import * as $int from "../gleam/int.mjs";
|
||||
import * as $order from "../gleam/order.mjs";
|
||||
import * as $string from "../gleam/string.mjs";
|
||||
import {
|
||||
bit_array_from_string as from_string,
|
||||
bit_array_bit_size as bit_size,
|
||||
bit_array_byte_size as byte_size,
|
||||
bit_array_pad_to_bytes as pad_to_bytes,
|
||||
bit_array_slice as slice,
|
||||
bit_array_concat as concat,
|
||||
base64_encode,
|
||||
base64_decode as decode64,
|
||||
base16_encode,
|
||||
base16_decode,
|
||||
bit_array_to_int_and_size,
|
||||
bit_array_starts_with as starts_with,
|
||||
bit_array_to_string as to_string,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export {
|
||||
base16_decode,
|
||||
base16_encode,
|
||||
base64_encode,
|
||||
bit_size,
|
||||
byte_size,
|
||||
concat,
|
||||
from_string,
|
||||
pad_to_bytes,
|
||||
slice,
|
||||
starts_with,
|
||||
to_string,
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new bit array by joining two bit arrays.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* append(to: from_string("butter"), suffix: from_string("fly"))
|
||||
* // -> from_string("butterfly")
|
||||
* ```
|
||||
*/
|
||||
export function append(first, second) {
|
||||
return concat(toList([first, second]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a base 64 encoded string into a `BitArray`.
|
||||
*/
|
||||
export function base64_decode(encoded) {
|
||||
let _block;
|
||||
let $ = byte_size(from_string(encoded)) % 4;
|
||||
if ($ === 0) {
|
||||
_block = encoded;
|
||||
} else {
|
||||
let n = $;
|
||||
_block = $string.append(encoded, $string.repeat("=", 4 - n));
|
||||
}
|
||||
let padded = _block;
|
||||
return decode64(padded);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a `BitArray` into a base 64 encoded string with URL and filename
|
||||
* safe alphabet.
|
||||
*
|
||||
* If the bit array does not contain a whole number of bytes then it is padded
|
||||
* with zero bits prior to being encoded.
|
||||
*/
|
||||
export function base64_url_encode(input, padding) {
|
||||
let _pipe = input;
|
||||
let _pipe$1 = base64_encode(_pipe, padding);
|
||||
let _pipe$2 = $string.replace(_pipe$1, "+", "-");
|
||||
return $string.replace(_pipe$2, "/", "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a base 64 encoded string with URL and filename safe alphabet into a
|
||||
* `BitArray`.
|
||||
*/
|
||||
export function base64_url_decode(encoded) {
|
||||
let _pipe = encoded;
|
||||
let _pipe$1 = $string.replace(_pipe, "-", "+");
|
||||
let _pipe$2 = $string.replace(_pipe$1, "_", "/");
|
||||
return base64_decode(_pipe$2);
|
||||
}
|
||||
|
||||
function inspect_loop(loop$input, loop$accumulator) {
|
||||
while (true) {
|
||||
let input = loop$input;
|
||||
let accumulator = loop$accumulator;
|
||||
if (input.bitSize === 0) {
|
||||
return accumulator;
|
||||
} else if (input.bitSize === 1) {
|
||||
let x = bitArraySliceToInt(input, 0, 1, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(1)";
|
||||
} else if (input.bitSize === 2) {
|
||||
let x = bitArraySliceToInt(input, 0, 2, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(2)";
|
||||
} else if (input.bitSize === 3) {
|
||||
let x = bitArraySliceToInt(input, 0, 3, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(3)";
|
||||
} else if (input.bitSize === 4) {
|
||||
let x = bitArraySliceToInt(input, 0, 4, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(4)";
|
||||
} else if (input.bitSize === 5) {
|
||||
let x = bitArraySliceToInt(input, 0, 5, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(5)";
|
||||
} else if (input.bitSize === 6) {
|
||||
let x = bitArraySliceToInt(input, 0, 6, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(6)";
|
||||
} else if (input.bitSize === 7) {
|
||||
let x = bitArraySliceToInt(input, 0, 7, true, false);
|
||||
return (accumulator + $int.to_string(x)) + ":size(7)";
|
||||
} else if (input.bitSize >= 8) {
|
||||
let x = input.byteAt(0);
|
||||
let rest = bitArraySlice(input, 8);
|
||||
let _block;
|
||||
if (rest.bitSize === 0) {
|
||||
_block = "";
|
||||
} else {
|
||||
_block = ", ";
|
||||
}
|
||||
let suffix = _block;
|
||||
let accumulator$1 = (accumulator + $int.to_string(x)) + suffix;
|
||||
loop$input = rest;
|
||||
loop$accumulator = accumulator$1;
|
||||
} else {
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a bit array to a string containing the decimal value of each byte.
|
||||
*
|
||||
* Use this over `string.inspect` when you have a bit array you want printed
|
||||
* in the array syntax even if it is valid UTF-8.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* inspect(<<0, 20, 0x20, 255>>)
|
||||
* // -> "<<0, 20, 32, 255>>"
|
||||
*
|
||||
* inspect(<<100, 5:3>>)
|
||||
* // -> "<<100, 5:size(3)>>"
|
||||
* ```
|
||||
*/
|
||||
export function inspect(input) {
|
||||
return inspect_loop(input, "<<") + ">>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two bit arrays as sequences of bytes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* compare(<<1>>, <<2>>)
|
||||
* // -> Lt
|
||||
*
|
||||
* compare(<<"AB":utf8>>, <<"AA":utf8>>)
|
||||
* // -> Gt
|
||||
*
|
||||
* compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>)
|
||||
* // -> Eq
|
||||
* ```
|
||||
*/
|
||||
export function compare(loop$a, loop$b) {
|
||||
while (true) {
|
||||
let a = loop$a;
|
||||
let b = loop$b;
|
||||
if (a.bitSize >= 8) {
|
||||
if (b.bitSize >= 8) {
|
||||
let first_byte = a.byteAt(0);
|
||||
let first_rest = bitArraySlice(a, 8);
|
||||
let second_byte = b.byteAt(0);
|
||||
let second_rest = bitArraySlice(b, 8);
|
||||
let f = first_byte;
|
||||
let s = second_byte;
|
||||
if (f > s) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let f$1 = first_byte;
|
||||
let s$1 = second_byte;
|
||||
if (f$1 < s$1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
loop$a = first_rest;
|
||||
loop$b = second_rest;
|
||||
}
|
||||
}
|
||||
} else if (b.bitSize === 0) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let first = a;
|
||||
let second = b;
|
||||
let $ = bit_array_to_int_and_size(first);
|
||||
let $1 = bit_array_to_int_and_size(second);
|
||||
let a$1 = $[0];
|
||||
let b$1 = $1[0];
|
||||
if (a$1 > b$1) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let a$2 = $[0];
|
||||
let b$2 = $1[0];
|
||||
if (a$2 < b$2) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
let size_a = $[1];
|
||||
let size_b = $1[1];
|
||||
if (size_a > size_b) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let size_a$1 = $[1];
|
||||
let size_b$1 = $1[1];
|
||||
if (size_a$1 < size_b$1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
return new $order.Eq();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (b.bitSize === 0) {
|
||||
if (a.bitSize === 0) {
|
||||
return new $order.Eq();
|
||||
} else {
|
||||
return new $order.Gt();
|
||||
}
|
||||
} else if (a.bitSize === 0) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
let first = a;
|
||||
let second = b;
|
||||
let $ = bit_array_to_int_and_size(first);
|
||||
let $1 = bit_array_to_int_and_size(second);
|
||||
let a$1 = $[0];
|
||||
let b$1 = $1[0];
|
||||
if (a$1 > b$1) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let a$2 = $[0];
|
||||
let b$2 = $1[0];
|
||||
if (a$2 < b$2) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
let size_a = $[1];
|
||||
let size_b = $1[1];
|
||||
if (size_a > size_b) {
|
||||
return new $order.Gt();
|
||||
} else {
|
||||
let size_a$1 = $[1];
|
||||
let size_b$1 = $1[1];
|
||||
if (size_a$1 < size_b$1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
return new $order.Eq();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests to see whether a bit array is valid UTF-8.
|
||||
*/
|
||||
export function is_utf8(bits) {
|
||||
return is_utf8_loop(bits);
|
||||
}
|
||||
|
||||
function is_utf8_loop(bits) {
|
||||
let $ = to_string(bits);
|
||||
if ($ instanceof Ok) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
313
build/dev/javascript/gleam_stdlib/gleam/bool.mjs
Normal file
313
build/dev/javascript/gleam_stdlib/gleam/bool.mjs
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/**
|
||||
* Returns the and of two bools, but it evaluates both arguments.
|
||||
*
|
||||
* It's the function equivalent of the `&&` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* and(True, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* and(False, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* False |> and(True)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function and(a, b) {
|
||||
return a && b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the or of two bools, but it evaluates both arguments.
|
||||
*
|
||||
* It's the function equivalent of the `||` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* or(True, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(False, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* False |> or(True)
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function or(a, b) {
|
||||
return a || b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the opposite bool value.
|
||||
*
|
||||
* This is the same as the `!` or `not` operators in some other languages.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* negate(True)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* negate(False)
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function negate(bool) {
|
||||
return !bool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nor of two bools.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* nor(False, False)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nor(False, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nor(True, False)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nor(True, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function nor(a, b) {
|
||||
return !(a || b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nand of two bools.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* nand(False, False)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nand(False, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nand(True, False)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* nand(True, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function nand(a, b) {
|
||||
return !(a && b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclusive or of two bools.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_or(False, False)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_or(False, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_or(True, False)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_or(True, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function exclusive_or(a, b) {
|
||||
return a !== b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exclusive nor of two bools.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_nor(False, False)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_nor(False, True)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_nor(True, False)
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* exclusive_nor(True, True)
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function exclusive_nor(a, b) {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the given bool.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_string(True)
|
||||
* // -> "True"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_string(False)
|
||||
* // -> "False"
|
||||
* ```
|
||||
*/
|
||||
export function to_string(bool) {
|
||||
if (bool) {
|
||||
return "True";
|
||||
} else {
|
||||
return "False";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a callback function if the given bool is `False`, otherwise return a
|
||||
* default value.
|
||||
*
|
||||
* With a `use` expression this function can simulate the early-return pattern
|
||||
* found in some other programming languages.
|
||||
*
|
||||
* In a procedural language:
|
||||
*
|
||||
* ```js
|
||||
* if (predicate) return value;
|
||||
* // ...
|
||||
* ```
|
||||
*
|
||||
* In Gleam with a `use` expression:
|
||||
*
|
||||
* ```gleam
|
||||
* use <- guard(when: predicate, return: value)
|
||||
* // ...
|
||||
* ```
|
||||
*
|
||||
* Like everything in Gleam `use` is an expression, so it short circuits the
|
||||
* current block, not the entire function. As a result you can assign the value
|
||||
* to a variable:
|
||||
*
|
||||
* ```gleam
|
||||
* let x = {
|
||||
* use <- guard(when: predicate, return: value)
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Note that unlike in procedural languages the `return` value is evaluated
|
||||
* even when the predicate is `False`, so it is advisable not to perform
|
||||
* expensive computation nor side-effects there.
|
||||
*
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let name = ""
|
||||
* use <- guard(when: name == "", return: "Welcome!")
|
||||
* "Hello, " <> name
|
||||
* // -> "Welcome!"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* let name = "Kamaka"
|
||||
* use <- guard(when: name == "", return: "Welcome!")
|
||||
* "Hello, " <> name
|
||||
* // -> "Hello, Kamaka"
|
||||
* ```
|
||||
*/
|
||||
export function guard(requirement, consequence, alternative) {
|
||||
if (requirement) {
|
||||
return consequence;
|
||||
} else {
|
||||
return alternative();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a callback function if the given bool is `True`, otherwise runs an
|
||||
* alternative callback function.
|
||||
*
|
||||
* Useful when further computation should be delayed regardless of the given
|
||||
* bool's value.
|
||||
*
|
||||
* See [`guard`](#guard) for more info.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let name = "Kamaka"
|
||||
* let inquiry = fn() { "How may we address you?" }
|
||||
* use <- lazy_guard(when: name == "", return: inquiry)
|
||||
* "Hello, " <> name
|
||||
* // -> "Hello, Kamaka"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* let name = ""
|
||||
* let greeting = fn() { "Hello, " <> name }
|
||||
* use <- lazy_guard(when: name == "", otherwise: greeting)
|
||||
* let number = int.random(99)
|
||||
* let name = "User " <> int.to_string(number)
|
||||
* "Welcome, " <> name
|
||||
* // -> "Welcome, User 54"
|
||||
* ```
|
||||
*/
|
||||
export function lazy_guard(requirement, consequence, alternative) {
|
||||
if (requirement) {
|
||||
return consequence();
|
||||
} else {
|
||||
return alternative();
|
||||
}
|
||||
}
|
||||
225
build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs
Normal file
225
build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
import {
|
||||
toList,
|
||||
Empty as $Empty,
|
||||
prepend as listPrepend,
|
||||
CustomType as $CustomType,
|
||||
} from "../gleam.mjs";
|
||||
import * as $bit_array from "../gleam/bit_array.mjs";
|
||||
import * as $list from "../gleam/list.mjs";
|
||||
import * as $string_tree from "../gleam/string_tree.mjs";
|
||||
|
||||
class Bytes extends $CustomType {
|
||||
constructor($0) {
|
||||
super();
|
||||
this[0] = $0;
|
||||
}
|
||||
}
|
||||
|
||||
class Text extends $CustomType {
|
||||
constructor($0) {
|
||||
super();
|
||||
this[0] = $0;
|
||||
}
|
||||
}
|
||||
|
||||
class Many extends $CustomType {
|
||||
constructor($0) {
|
||||
super();
|
||||
this[0] = $0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a bytes tree onto the end of another.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function append_tree(first, second) {
|
||||
if (second instanceof Bytes) {
|
||||
return new Many(toList([first, second]));
|
||||
} else if (second instanceof Text) {
|
||||
return new Many(toList([first, second]));
|
||||
} else {
|
||||
let trees = second[0];
|
||||
return new Many(listPrepend(first, trees));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends a bytes tree onto the start of another.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function prepend_tree(second, first) {
|
||||
return append_tree(first, second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a list of bytes trees into a single one.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function concat(trees) {
|
||||
return new Many(trees);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty `BytesTree`. Useful as the start of a pipe chaining many
|
||||
* trees together.
|
||||
*/
|
||||
export function new$() {
|
||||
return concat(toList([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bytes tree from a string.
|
||||
*
|
||||
* Runs in constant time when running on Erlang.
|
||||
* Runs in linear time otherwise.
|
||||
*/
|
||||
export function from_string(string) {
|
||||
return new Text($string_tree.from_string(string));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends a string onto the start of a bytes tree.
|
||||
*
|
||||
* Runs in constant time when running on Erlang.
|
||||
* Runs in linear time with the length of the string otherwise.
|
||||
*/
|
||||
export function prepend_string(second, first) {
|
||||
return append_tree(from_string(first), second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a string onto the end of a bytes tree.
|
||||
*
|
||||
* Runs in constant time when running on Erlang.
|
||||
* Runs in linear time with the length of the string otherwise.
|
||||
*/
|
||||
export function append_string(first, second) {
|
||||
return append_tree(first, from_string(second));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bytes tree from a string tree.
|
||||
*
|
||||
* Runs in constant time when running on Erlang.
|
||||
* Runs in linear time otherwise.
|
||||
*/
|
||||
export function from_string_tree(tree) {
|
||||
return new Text(tree);
|
||||
}
|
||||
|
||||
function wrap_list(bits) {
|
||||
return new Bytes(bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bytes tree from a bit array.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function from_bit_array(bits) {
|
||||
let _pipe = bits;
|
||||
let _pipe$1 = $bit_array.pad_to_bytes(_pipe);
|
||||
return wrap_list(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends a bit array to the start of a bytes tree.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function prepend(second, first) {
|
||||
return append_tree(from_bit_array(first), second);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a bit array to the end of a bytes tree.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function append(first, second) {
|
||||
return append_tree(first, from_bit_array(second));
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins a list of bit arrays into a single bytes tree.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function concat_bit_arrays(bits) {
|
||||
let _pipe = bits;
|
||||
let _pipe$1 = $list.map(_pipe, from_bit_array);
|
||||
return concat(_pipe$1);
|
||||
}
|
||||
|
||||
function to_list(loop$stack, loop$acc) {
|
||||
while (true) {
|
||||
let stack = loop$stack;
|
||||
let acc = loop$acc;
|
||||
if (stack instanceof $Empty) {
|
||||
return acc;
|
||||
} else {
|
||||
let $ = stack.head;
|
||||
if ($ instanceof $Empty) {
|
||||
let remaining_stack = stack.tail;
|
||||
loop$stack = remaining_stack;
|
||||
loop$acc = acc;
|
||||
} else {
|
||||
let $1 = $.head;
|
||||
if ($1 instanceof Bytes) {
|
||||
let remaining_stack = stack.tail;
|
||||
let rest = $.tail;
|
||||
let bits = $1[0];
|
||||
loop$stack = listPrepend(rest, remaining_stack);
|
||||
loop$acc = listPrepend(bits, acc);
|
||||
} else if ($1 instanceof Text) {
|
||||
let remaining_stack = stack.tail;
|
||||
let rest = $.tail;
|
||||
let tree = $1[0];
|
||||
let bits = $bit_array.from_string($string_tree.to_string(tree));
|
||||
loop$stack = listPrepend(rest, remaining_stack);
|
||||
loop$acc = listPrepend(bits, acc);
|
||||
} else {
|
||||
let remaining_stack = stack.tail;
|
||||
let rest = $.tail;
|
||||
let trees = $1[0];
|
||||
loop$stack = listPrepend(trees, listPrepend(rest, remaining_stack));
|
||||
loop$acc = acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a bytes tree into a bit array.
|
||||
*
|
||||
* Runs in linear time.
|
||||
*
|
||||
* When running on Erlang this function is implemented natively by the
|
||||
* virtual machine and is highly optimised.
|
||||
*/
|
||||
export function to_bit_array(tree) {
|
||||
let _pipe = toList([toList([tree])]);
|
||||
let _pipe$1 = to_list(_pipe, toList([]));
|
||||
let _pipe$2 = $list.reverse(_pipe$1);
|
||||
return $bit_array.concat(_pipe$2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the bytes tree's content in bytes.
|
||||
*
|
||||
* Runs in linear time.
|
||||
*/
|
||||
export function byte_size(tree) {
|
||||
let _pipe = toList([toList([tree])]);
|
||||
let _pipe$1 = to_list(_pipe, toList([]));
|
||||
return $list.fold(
|
||||
_pipe$1,
|
||||
0,
|
||||
(acc, bits) => { return $bit_array.byte_size(bits) + acc; },
|
||||
);
|
||||
}
|
||||
534
build/dev/javascript/gleam_stdlib/gleam/dict.mjs
Normal file
534
build/dev/javascript/gleam_stdlib/gleam/dict.mjs
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend, isEqual } from "../gleam.mjs";
|
||||
import * as $option from "../gleam/option.mjs";
|
||||
import {
|
||||
map_size as size,
|
||||
map_to_list as to_list,
|
||||
new_map as new$,
|
||||
map_get as get,
|
||||
map_insert as do_insert,
|
||||
map_remove as do_delete,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export { get, new$, size, to_list };
|
||||
|
||||
/**
|
||||
* Determines whether or not the dict is empty.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> is_empty
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert("b", 1) |> is_empty
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_empty(dict) {
|
||||
return size(dict) === 0;
|
||||
}
|
||||
|
||||
function do_has_key(key, dict) {
|
||||
return !isEqual(get(dict, key), new Error(undefined));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a value present in the dict for a given key.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert("a", 0) |> has_key("a")
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert("a", 0) |> has_key("b")
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function has_key(dict, key) {
|
||||
return do_has_key(key, dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a value into the dict with the given key.
|
||||
*
|
||||
* If the dict already has a value for the given key then the value is
|
||||
* replaced with the new value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert("a", 0)
|
||||
* // -> from_list([#("a", 0)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert("a", 0) |> insert("a", 5)
|
||||
* // -> from_list([#("a", 5)])
|
||||
* ```
|
||||
*/
|
||||
export function insert(dict, key, value) {
|
||||
return do_insert(key, value, dict);
|
||||
}
|
||||
|
||||
function from_list_loop(loop$list, loop$initial) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let initial = loop$initial;
|
||||
if (list instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let rest = list.tail;
|
||||
let key = list.head[0];
|
||||
let value = list.head[1];
|
||||
loop$list = rest;
|
||||
loop$initial = insert(initial, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a list of 2-element tuples `#(key, value)` to a dict.
|
||||
*
|
||||
* If two tuples have the same key the last one in the list will be the one
|
||||
* that is present in the dict.
|
||||
*/
|
||||
export function from_list(list) {
|
||||
return from_list_loop(list, new$());
|
||||
}
|
||||
|
||||
function reverse_and_concat(loop$remaining, loop$accumulator) {
|
||||
while (true) {
|
||||
let remaining = loop$remaining;
|
||||
let accumulator = loop$accumulator;
|
||||
if (remaining instanceof $Empty) {
|
||||
return accumulator;
|
||||
} else {
|
||||
let first = remaining.head;
|
||||
let rest = remaining.tail;
|
||||
loop$remaining = rest;
|
||||
loop$accumulator = listPrepend(first, accumulator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function do_keys_loop(loop$list, loop$acc) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let acc = loop$acc;
|
||||
if (list instanceof $Empty) {
|
||||
return reverse_and_concat(acc, toList([]));
|
||||
} else {
|
||||
let rest = list.tail;
|
||||
let key = list.head[0];
|
||||
loop$list = rest;
|
||||
loop$acc = listPrepend(key, acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all keys in a given dict.
|
||||
*
|
||||
* Dicts are not ordered so the keys are not returned in any specific order. Do
|
||||
* not write code that relies on the order keys are returned by this function
|
||||
* as it may change in later versions of Gleam or Erlang.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> keys
|
||||
* // -> ["a", "b"]
|
||||
* ```
|
||||
*/
|
||||
export function keys(dict) {
|
||||
return do_keys_loop(to_list(dict), toList([]));
|
||||
}
|
||||
|
||||
function do_values_loop(loop$list, loop$acc) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let acc = loop$acc;
|
||||
if (list instanceof $Empty) {
|
||||
return reverse_and_concat(acc, toList([]));
|
||||
} else {
|
||||
let rest = list.tail;
|
||||
let value = list.head[1];
|
||||
loop$list = rest;
|
||||
loop$acc = listPrepend(value, acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all values in a given dict.
|
||||
*
|
||||
* Dicts are not ordered so the values are not returned in any specific order. Do
|
||||
* not write code that relies on the order values are returned by this function
|
||||
* as it may change in later versions of Gleam or Erlang.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> values
|
||||
* // -> [0, 1]
|
||||
* ```
|
||||
*/
|
||||
export function values(dict) {
|
||||
let list_of_pairs = to_list(dict);
|
||||
return do_values_loop(list_of_pairs, toList([]));
|
||||
}
|
||||
|
||||
function do_take_loop(loop$dict, loop$desired_keys, loop$acc) {
|
||||
while (true) {
|
||||
let dict = loop$dict;
|
||||
let desired_keys = loop$desired_keys;
|
||||
let acc = loop$acc;
|
||||
let insert$1 = (taken, key) => {
|
||||
let $ = get(dict, key);
|
||||
if ($ instanceof Ok) {
|
||||
let value = $[0];
|
||||
return insert(taken, key, value);
|
||||
} else {
|
||||
return taken;
|
||||
}
|
||||
};
|
||||
if (desired_keys instanceof $Empty) {
|
||||
return acc;
|
||||
} else {
|
||||
let first = desired_keys.head;
|
||||
let rest = desired_keys.tail;
|
||||
loop$dict = dict;
|
||||
loop$desired_keys = rest;
|
||||
loop$acc = insert$1(acc, first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function do_take(desired_keys, dict) {
|
||||
return do_take_loop(dict, desired_keys, new$());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a given dict, only including any entries for which the
|
||||
* keys are in a given list.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)])
|
||||
* |> take(["b"])
|
||||
* // -> from_list([#("b", 1)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)])
|
||||
* |> take(["a", "b", "c"])
|
||||
* // -> from_list([#("a", 0), #("b", 1)])
|
||||
* ```
|
||||
*/
|
||||
export function take(dict, desired_keys) {
|
||||
return do_take(desired_keys, dict);
|
||||
}
|
||||
|
||||
function insert_pair(dict, pair) {
|
||||
return insert(dict, pair[0], pair[1]);
|
||||
}
|
||||
|
||||
function fold_inserts(loop$new_entries, loop$dict) {
|
||||
while (true) {
|
||||
let new_entries = loop$new_entries;
|
||||
let dict = loop$dict;
|
||||
if (new_entries instanceof $Empty) {
|
||||
return dict;
|
||||
} else {
|
||||
let first = new_entries.head;
|
||||
let rest = new_entries.tail;
|
||||
loop$new_entries = rest;
|
||||
loop$dict = insert_pair(dict, first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a pair of given dicts by combining their entries.
|
||||
*
|
||||
* If there are entries with the same keys in both dicts the entry from the
|
||||
* second dict takes precedence.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let a = from_list([#("a", 0), #("b", 1)])
|
||||
* let b = from_list([#("b", 2), #("c", 3)])
|
||||
* merge(a, b)
|
||||
* // -> from_list([#("a", 0), #("b", 2), #("c", 3)])
|
||||
* ```
|
||||
*/
|
||||
export function merge(dict, new_entries) {
|
||||
let _pipe = new_entries;
|
||||
let _pipe$1 = to_list(_pipe);
|
||||
return fold_inserts(_pipe$1, dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a given dict with all the same entries except for the
|
||||
* one with a given key, if it exists.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> delete("a")
|
||||
* // -> from_list([#("b", 1)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> delete("c")
|
||||
* // -> from_list([#("a", 0), #("b", 1)])
|
||||
* ```
|
||||
*/
|
||||
export function delete$(dict, key) {
|
||||
return do_delete(key, dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a given dict with all the same entries except any with
|
||||
* keys found in a given list.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> drop(["a"])
|
||||
* // -> from_list([#("b", 1)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> drop(["c"])
|
||||
* // -> from_list([#("a", 0), #("b", 1)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)]) |> drop(["a", "b", "c"])
|
||||
* // -> from_list([])
|
||||
* ```
|
||||
*/
|
||||
export function drop(loop$dict, loop$disallowed_keys) {
|
||||
while (true) {
|
||||
let dict = loop$dict;
|
||||
let disallowed_keys = loop$disallowed_keys;
|
||||
if (disallowed_keys instanceof $Empty) {
|
||||
return dict;
|
||||
} else {
|
||||
let first = disallowed_keys.head;
|
||||
let rest = disallowed_keys.tail;
|
||||
loop$dict = delete$(dict, first);
|
||||
loop$disallowed_keys = rest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict with one entry inserted or updated using a given function.
|
||||
*
|
||||
* If there was not an entry in the dict for the given key then the function
|
||||
* gets `None` as its argument, otherwise it gets `Some(value)`.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* ```gleam
|
||||
* let dict = from_list([#("a", 0)])
|
||||
* let increment = fn(x) {
|
||||
* case x {
|
||||
* Some(i) -> i + 1
|
||||
* None -> 0
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* upsert(dict, "a", increment)
|
||||
* // -> from_list([#("a", 1)])
|
||||
*
|
||||
* upsert(dict, "b", increment)
|
||||
* // -> from_list([#("a", 0), #("b", 0)])
|
||||
* ```
|
||||
*/
|
||||
export function upsert(dict, key, fun) {
|
||||
let $ = get(dict, key);
|
||||
if ($ instanceof Ok) {
|
||||
let value = $[0];
|
||||
return insert(dict, key, fun(new $option.Some(value)));
|
||||
} else {
|
||||
return insert(dict, key, fun(new $option.None()));
|
||||
}
|
||||
}
|
||||
|
||||
function fold_loop(loop$list, loop$initial, loop$fun) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let initial = loop$initial;
|
||||
let fun = loop$fun;
|
||||
if (list instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let rest = list.tail;
|
||||
let k = list.head[0];
|
||||
let v = list.head[1];
|
||||
loop$list = rest;
|
||||
loop$initial = fun(initial, k, v);
|
||||
loop$fun = fun;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines all entries into a single value by calling a given function on each
|
||||
* one.
|
||||
*
|
||||
* Dicts are not ordered so the values are not returned in any specific order. Do
|
||||
* not write code that relies on the order entries are used by this function
|
||||
* as it may change in later versions of Gleam or Erlang.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let dict = from_list([#("a", 1), #("b", 3), #("c", 9)])
|
||||
* fold(dict, 0, fn(accumulator, key, value) { accumulator + value })
|
||||
* // -> 13
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/string
|
||||
*
|
||||
* let dict = from_list([#("a", 1), #("b", 3), #("c", 9)])
|
||||
* fold(dict, "", fn(accumulator, key, value) {
|
||||
* string.append(accumulator, key)
|
||||
* })
|
||||
* // -> "abc"
|
||||
* ```
|
||||
*/
|
||||
export function fold(dict, initial, fun) {
|
||||
return fold_loop(to_list(dict), initial, fun);
|
||||
}
|
||||
|
||||
function do_map_values(f, dict) {
|
||||
let f$1 = (dict, k, v) => { return insert(dict, k, f(k, v)); };
|
||||
return fold(dict, new$(), f$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all values in a given dict by calling a given function on each key
|
||||
* and value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#(3, 3), #(2, 4)])
|
||||
* |> map_values(fn(key, value) { key * value })
|
||||
* // -> from_list([#(3, 9), #(2, 8)])
|
||||
* ```
|
||||
*/
|
||||
export function map_values(dict, fun) {
|
||||
return do_map_values(fun, dict);
|
||||
}
|
||||
|
||||
function do_filter(f, dict) {
|
||||
let insert$1 = (dict, k, v) => {
|
||||
let $ = f(k, v);
|
||||
if ($) {
|
||||
return insert(dict, k, v);
|
||||
} else {
|
||||
return dict;
|
||||
}
|
||||
};
|
||||
return fold(dict, new$(), insert$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a given dict, minus any entries that a given function
|
||||
* returns `False` for.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)])
|
||||
* |> filter(fn(key, value) { value != 0 })
|
||||
* // -> from_list([#("b", 1)])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([#("a", 0), #("b", 1)])
|
||||
* |> filter(fn(key, value) { True })
|
||||
* // -> from_list([#("a", 0), #("b", 1)])
|
||||
* ```
|
||||
*/
|
||||
export function filter(dict, predicate) {
|
||||
return do_filter(predicate, dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function for each key and value in a dict, discarding the return
|
||||
* value.
|
||||
*
|
||||
* Useful for producing a side effect for every item of a dict.
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/io
|
||||
*
|
||||
* let dict = from_list([#("a", "apple"), #("b", "banana"), #("c", "cherry")])
|
||||
*
|
||||
* each(dict, fn(k, v) {
|
||||
* io.println(key <> " => " <> value)
|
||||
* })
|
||||
* // -> Nil
|
||||
* // a => apple
|
||||
* // b => banana
|
||||
* // c => cherry
|
||||
* ```
|
||||
*
|
||||
* The order of elements in the iteration is an implementation detail that
|
||||
* should not be relied upon.
|
||||
*/
|
||||
export function each(dict, fun) {
|
||||
return fold(
|
||||
dict,
|
||||
undefined,
|
||||
(nil, k, v) => {
|
||||
fun(k, v);
|
||||
return nil;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dict from a pair of given dicts by combining their entries.
|
||||
*
|
||||
* If there are entries with the same keys in both dicts the given function is
|
||||
* used to determine the new value to use in the resulting dict.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let a = from_list([#("a", 0), #("b", 1)])
|
||||
* let b = from_list([#("a", 2), #("c", 3)])
|
||||
* combine(a, b, fn(one, other) { one + other })
|
||||
* // -> from_list([#("a", 2), #("b", 1), #("c", 3)])
|
||||
* ```
|
||||
*/
|
||||
export function combine(dict, other, fun) {
|
||||
return fold(
|
||||
dict,
|
||||
other,
|
||||
(acc, key, value) => {
|
||||
let $ = get(acc, key);
|
||||
if ($ instanceof Ok) {
|
||||
let other_value = $[0];
|
||||
return insert(acc, key, fun(value, other_value));
|
||||
} else {
|
||||
return insert(acc, key, value);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
35
build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs
Normal file
35
build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import * as $dict from "../gleam/dict.mjs";
|
||||
import {
|
||||
classify_dynamic as classify,
|
||||
identity as bool,
|
||||
identity as string,
|
||||
identity as float,
|
||||
identity as int,
|
||||
identity as bit_array,
|
||||
identity as list,
|
||||
list_to_array as array,
|
||||
identity as cast,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export { array, bit_array, bool, classify, float, int, list, string };
|
||||
|
||||
/**
|
||||
* Create a dynamic value made an unordered series of keys and values, where
|
||||
* the keys are unique.
|
||||
*
|
||||
* On Erlang this will be a map, on JavaScript this will be a Gleam dict
|
||||
* object.
|
||||
*/
|
||||
export function properties(entries) {
|
||||
return cast($dict.from_list(entries));
|
||||
}
|
||||
|
||||
/**
|
||||
* A dynamic value representing nothing.
|
||||
*
|
||||
* On Erlang this will be the atom `nil`, on JavaScript this will be
|
||||
* `undefined`.
|
||||
*/
|
||||
export function nil() {
|
||||
return cast(undefined);
|
||||
}
|
||||
947
build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs
Normal file
947
build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs
Normal file
|
|
@ -0,0 +1,947 @@
|
|||
import {
|
||||
Ok,
|
||||
Error,
|
||||
toList,
|
||||
Empty as $Empty,
|
||||
prepend as listPrepend,
|
||||
CustomType as $CustomType,
|
||||
isEqual,
|
||||
} from "../../gleam.mjs";
|
||||
import * as $bit_array from "../../gleam/bit_array.mjs";
|
||||
import * as $dict from "../../gleam/dict.mjs";
|
||||
import * as $dynamic from "../../gleam/dynamic.mjs";
|
||||
import * as $int from "../../gleam/int.mjs";
|
||||
import * as $list from "../../gleam/list.mjs";
|
||||
import * as $option from "../../gleam/option.mjs";
|
||||
import { None, Some } from "../../gleam/option.mjs";
|
||||
import {
|
||||
index as bare_index,
|
||||
int as dynamic_int,
|
||||
float as dynamic_float,
|
||||
bit_array as dynamic_bit_array,
|
||||
list as decode_list,
|
||||
dict as decode_dict,
|
||||
identity as cast,
|
||||
is_null,
|
||||
string as dynamic_string,
|
||||
} from "../../gleam_stdlib.mjs";
|
||||
|
||||
export class DecodeError extends $CustomType {
|
||||
constructor(expected, found, path) {
|
||||
super();
|
||||
this.expected = expected;
|
||||
this.found = found;
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
export const DecodeError$DecodeError = (expected, found, path) =>
|
||||
new DecodeError(expected, found, path);
|
||||
export const DecodeError$isDecodeError = (value) =>
|
||||
value instanceof DecodeError;
|
||||
export const DecodeError$DecodeError$expected = (value) => value.expected;
|
||||
export const DecodeError$DecodeError$0 = (value) => value.expected;
|
||||
export const DecodeError$DecodeError$found = (value) => value.found;
|
||||
export const DecodeError$DecodeError$1 = (value) => value.found;
|
||||
export const DecodeError$DecodeError$path = (value) => value.path;
|
||||
export const DecodeError$DecodeError$2 = (value) => value.path;
|
||||
|
||||
class Decoder extends $CustomType {
|
||||
constructor(function$) {
|
||||
super();
|
||||
this.function = function$;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a decoder on a `Dynamic` value, decoding the value if it is of the
|
||||
* desired type, or returning errors.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = {
|
||||
* use name <- decode.field("email", decode.string)
|
||||
* use email <- decode.field("password", decode.string)
|
||||
* decode.success(SignUp(name: name, email: email))
|
||||
* }
|
||||
*
|
||||
* decode.run(data, decoder)
|
||||
* ```
|
||||
*/
|
||||
export function run(data, decoder) {
|
||||
let $ = decoder.function(data);
|
||||
let maybe_invalid_data;
|
||||
let errors;
|
||||
maybe_invalid_data = $[0];
|
||||
errors = $[1];
|
||||
if (errors instanceof $Empty) {
|
||||
return new Ok(maybe_invalid_data);
|
||||
} else {
|
||||
return new Error(errors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalise a decoder having successfully extracted a value.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("email"), dynamic.string("lucy@example.com")),
|
||||
* #(dynamic.string("name"), dynamic.string("Lucy")),
|
||||
* ]))
|
||||
*
|
||||
* let decoder = {
|
||||
* use name <- decode.field("name", string)
|
||||
* use email <- decode.field("email", string)
|
||||
* decode.success(SignUp(name: name, email: email))
|
||||
* }
|
||||
*
|
||||
* let result = decode.run(data, decoder)
|
||||
* assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com"))
|
||||
* ```
|
||||
*/
|
||||
export function success(data) {
|
||||
return new Decoder((_) => { return [data, toList([])]; });
|
||||
}
|
||||
|
||||
function decode_dynamic(data) {
|
||||
return [data, toList([])];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a transformation function to any value decoded by the decoder.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = decode.int |> decode.map(int.to_string)
|
||||
* let result = decode.run(dynamic.int(1000), decoder)
|
||||
* assert result == Ok("1000")
|
||||
* ```
|
||||
*/
|
||||
export function map(decoder, transformer) {
|
||||
return new Decoder(
|
||||
(d) => {
|
||||
let $ = decoder.function(d);
|
||||
let data;
|
||||
let errors;
|
||||
data = $[0];
|
||||
errors = $[1];
|
||||
return [transformer(data), errors];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a transformation function to any errors returned by the decoder.
|
||||
*/
|
||||
export function map_errors(decoder, transformer) {
|
||||
return new Decoder(
|
||||
(d) => {
|
||||
let $ = decoder.function(d);
|
||||
let data;
|
||||
let errors;
|
||||
data = $[0];
|
||||
errors = $[1];
|
||||
return [data, transformer(errors)];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new decoder based upon the value of a previous decoder.
|
||||
*
|
||||
* This may be useful to run one previous decoder to use in further decoding.
|
||||
*/
|
||||
export function then$(decoder, next) {
|
||||
return new Decoder(
|
||||
(dynamic_data) => {
|
||||
let $ = decoder.function(dynamic_data);
|
||||
let data;
|
||||
let errors;
|
||||
data = $[0];
|
||||
errors = $[1];
|
||||
let decoder$1 = next(data);
|
||||
let $1 = decoder$1.function(dynamic_data);
|
||||
let layer;
|
||||
let data$1;
|
||||
layer = $1;
|
||||
data$1 = $1[0];
|
||||
if (errors instanceof $Empty) {
|
||||
return layer;
|
||||
} else {
|
||||
return [data$1, errors];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function run_decoders(loop$data, loop$failure, loop$decoders) {
|
||||
while (true) {
|
||||
let data = loop$data;
|
||||
let failure = loop$failure;
|
||||
let decoders = loop$decoders;
|
||||
if (decoders instanceof $Empty) {
|
||||
return failure;
|
||||
} else {
|
||||
let decoder = decoders.head;
|
||||
let decoders$1 = decoders.tail;
|
||||
let $ = decoder.function(data);
|
||||
let layer;
|
||||
let errors;
|
||||
layer = $;
|
||||
errors = $[1];
|
||||
if (errors instanceof $Empty) {
|
||||
return layer;
|
||||
} else {
|
||||
loop$data = data;
|
||||
loop$failure = failure;
|
||||
loop$decoders = decoders$1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new decoder from several other decoders. Each of the inner
|
||||
* decoders is run in turn, and the value from the first to succeed is used.
|
||||
*
|
||||
* If no decoder succeeds then the errors from the first decoder is used.
|
||||
* If you wish for different errors then you may wish to use the
|
||||
* `collapse_errors` or `map_errors` functions.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = decode.one_of(decode.string, or: [
|
||||
* decode.int |> decode.map(int.to_string),
|
||||
* decode.float |> decode.map(float.to_string),
|
||||
* ])
|
||||
* decode.run(dynamic.int(1000), decoder)
|
||||
* // -> Ok("1000")
|
||||
* ```
|
||||
*/
|
||||
export function one_of(first, alternatives) {
|
||||
return new Decoder(
|
||||
(dynamic_data) => {
|
||||
let $ = first.function(dynamic_data);
|
||||
let layer;
|
||||
let errors;
|
||||
layer = $;
|
||||
errors = $[1];
|
||||
if (errors instanceof $Empty) {
|
||||
return layer;
|
||||
} else {
|
||||
return run_decoders(dynamic_data, layer, alternatives);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a decoder that can refer to itself, useful for decoding deeply
|
||||
* nested data.
|
||||
*
|
||||
* Attempting to create a recursive decoder without this function could result
|
||||
* in an infinite loop. If you are using `field` or other `use`able functions
|
||||
* then you may not need to use this function.
|
||||
*
|
||||
* ```gleam
|
||||
* type Nested {
|
||||
* Nested(List(Nested))
|
||||
* Value(String)
|
||||
* }
|
||||
*
|
||||
* fn nested_decoder() -> decode.Decoder(Nested) {
|
||||
* use <- decode.recursive
|
||||
* decode.one_of(decode.string |> decode.map(Value), [
|
||||
* decode.list(nested_decoder()) |> decode.map(Nested),
|
||||
* ])
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function recursive(inner) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
let decoder = inner();
|
||||
return decoder.function(data);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes nullable values of a type decoded by with a given
|
||||
* decoder.
|
||||
*
|
||||
* This function can handle common representations of null on all runtimes, such as
|
||||
* `nil`, `null`, and `undefined` on Erlang, and `undefined` and `null` on
|
||||
* JavaScript.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.int(100), decode.optional(decode.int))
|
||||
* assert result == Ok(option.Some(100))
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.nil(), decode.optional(decode.int))
|
||||
* assert result == Ok(option.None)
|
||||
* ```
|
||||
*/
|
||||
export function optional(inner) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
let $ = is_null(data);
|
||||
if ($) {
|
||||
return [new $option.None(), toList([])];
|
||||
} else {
|
||||
let $1 = inner.function(data);
|
||||
let data$1;
|
||||
let errors;
|
||||
data$1 = $1[0];
|
||||
errors = $1[1];
|
||||
return [new $option.Some(data$1), errors];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes `Dynamic` values. This decoder never returns an error.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.float(3.14), decode.dynamic)
|
||||
* assert result == Ok(dynamic.float(3.14))
|
||||
* ```
|
||||
*/
|
||||
export const dynamic = /* @__PURE__ */ new Decoder(decode_dynamic);
|
||||
|
||||
/**
|
||||
* Construct a decode error for some unexpected dynamic data.
|
||||
*/
|
||||
export function decode_error(expected, found) {
|
||||
return toList([
|
||||
new DecodeError(expected, $dynamic.classify(found), toList([])),
|
||||
]);
|
||||
}
|
||||
|
||||
function run_dynamic_function(data, name, f) {
|
||||
let $ = f(data);
|
||||
if ($ instanceof Ok) {
|
||||
let data$1 = $[0];
|
||||
return [data$1, toList([])];
|
||||
} else {
|
||||
let zero = $[0];
|
||||
return [
|
||||
zero,
|
||||
toList([new DecodeError(name, $dynamic.classify(data), toList([]))]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function decode_bool(data) {
|
||||
let $ = isEqual(cast(true), data);
|
||||
if ($) {
|
||||
return [true, toList([])];
|
||||
} else {
|
||||
let $1 = isEqual(cast(false), data);
|
||||
if ($1) {
|
||||
return [false, toList([])];
|
||||
} else {
|
||||
return [false, decode_error("Bool", data)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function decode_int(data) {
|
||||
return run_dynamic_function(data, "Int", dynamic_int);
|
||||
}
|
||||
|
||||
function decode_float(data) {
|
||||
return run_dynamic_function(data, "Float", dynamic_float);
|
||||
}
|
||||
|
||||
function decode_bit_array(data) {
|
||||
return run_dynamic_function(data, "BitArray", dynamic_bit_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace all errors produced by a decoder with one single error for a named
|
||||
* expected type.
|
||||
*
|
||||
* This function may be useful if you wish to simplify errors before
|
||||
* presenting them to a user, particularly when using the `one_of` function.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = decode.string |> decode.collapse_errors("MyThing")
|
||||
* let result = decode.run(dynamic.int(1000), decoder)
|
||||
* assert result == Error([DecodeError("MyThing", "Int", [])])
|
||||
* ```
|
||||
*/
|
||||
export function collapse_errors(decoder, name) {
|
||||
return new Decoder(
|
||||
(dynamic_data) => {
|
||||
let $ = decoder.function(dynamic_data);
|
||||
let layer;
|
||||
let data;
|
||||
let errors;
|
||||
layer = $;
|
||||
data = $[0];
|
||||
errors = $[1];
|
||||
if (errors instanceof $Empty) {
|
||||
return layer;
|
||||
} else {
|
||||
return [data, decode_error(name, dynamic_data)];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a decoder that always fails. The parameter for this function is the
|
||||
* name of the type that has failed to decode.
|
||||
*/
|
||||
export function failure(zero, expected) {
|
||||
return new Decoder((d) => { return [zero, decode_error(expected, d)]; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a decoder for a new data type from a decoding function.
|
||||
*
|
||||
* This function is used for new primitive types. For example, you might
|
||||
* define a decoder for Erlang's pid type.
|
||||
*
|
||||
* A default "zero" value is also required to make a decoder. When this
|
||||
* decoder is used as part of a larger decoder this zero value used as
|
||||
* a placeholder so that the rest of the decoder can continue to run and
|
||||
* collect all decoding errors.
|
||||
*
|
||||
* If you were to make a decoder for the `String` type (rather than using the
|
||||
* build-in `string` decoder) you would define it like so:
|
||||
*
|
||||
* ```gleam
|
||||
* pub fn string_decoder() -> decode.Decoder(String) {
|
||||
* let default = ""
|
||||
* decode.new_primitive_decoder("String", fn(data) {
|
||||
* case dynamic.string(data) {
|
||||
* Ok(x) -> Ok(x)
|
||||
* Error(_) -> Error(default)
|
||||
* }
|
||||
* })
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function new_primitive_decoder(name, decoding_function) {
|
||||
return new Decoder(
|
||||
(d) => {
|
||||
let $ = decoding_function(d);
|
||||
if ($ instanceof Ok) {
|
||||
let t = $[0];
|
||||
return [t, toList([])];
|
||||
} else {
|
||||
let zero = $[0];
|
||||
return [
|
||||
zero,
|
||||
toList([new DecodeError(name, $dynamic.classify(d), toList([]))]),
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes `Bool` values.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.bool(True), decode.bool)
|
||||
* assert result == Ok(True)
|
||||
* ```
|
||||
*/
|
||||
export const bool = /* @__PURE__ */ new Decoder(decode_bool);
|
||||
|
||||
/**
|
||||
* A decoder that decodes `Int` values.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.int(147), decode.int)
|
||||
* assert result == Ok(147)
|
||||
* ```
|
||||
*/
|
||||
export const int = /* @__PURE__ */ new Decoder(decode_int);
|
||||
|
||||
/**
|
||||
* A decoder that decodes `Float` values.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.float(3.14), decode.float)
|
||||
* assert result == Ok(3.14)
|
||||
* ```
|
||||
*/
|
||||
export const float = /* @__PURE__ */ new Decoder(decode_float);
|
||||
|
||||
/**
|
||||
* A decoder that decodes `BitArray` values. This decoder never returns an error.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.bit_array(<<5, 7>>), decode.bit_array)
|
||||
* assert result == Ok(<<5, 7>>)
|
||||
* ```
|
||||
*/
|
||||
export const bit_array = /* @__PURE__ */ new Decoder(decode_bit_array);
|
||||
|
||||
function decode_string(data) {
|
||||
return run_dynamic_function(data, "String", dynamic_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes `String` values.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result = decode.run(dynamic.string("Hello!"), decode.string)
|
||||
* assert result == Ok("Hello!")
|
||||
* ```
|
||||
*/
|
||||
export const string = /* @__PURE__ */ new Decoder(decode_string);
|
||||
|
||||
function fold_dict(acc, key, value, key_decoder, value_decoder) {
|
||||
let $ = key_decoder(key);
|
||||
let $1 = $[1];
|
||||
if ($1 instanceof $Empty) {
|
||||
let key$1 = $[0];
|
||||
let $2 = value_decoder(value);
|
||||
let $3 = $2[1];
|
||||
if ($3 instanceof $Empty) {
|
||||
let value$1 = $2[0];
|
||||
let dict$1 = $dict.insert(acc[0], key$1, value$1);
|
||||
return [dict$1, acc[1]];
|
||||
} else {
|
||||
let errors = $3;
|
||||
return push_path([$dict.new$(), errors], toList(["values"]));
|
||||
}
|
||||
} else {
|
||||
let errors = $1;
|
||||
return push_path([$dict.new$(), errors], toList(["keys"]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes dicts where all keys and vales are decoded with
|
||||
* given decoders.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let values = dynamic.properties([
|
||||
* #(dynamic.string("one"), dynamic.int(1)),
|
||||
* #(dynamic.string("two"), dynamic.int(2)),
|
||||
* ])
|
||||
*
|
||||
* let result =
|
||||
* decode.run(values, decode.dict(decode.string, decode.int))
|
||||
* assert result == Ok(values)
|
||||
* ```
|
||||
*/
|
||||
export function dict(key, value) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
let $ = decode_dict(data);
|
||||
if ($ instanceof Ok) {
|
||||
let dict$1 = $[0];
|
||||
return $dict.fold(
|
||||
dict$1,
|
||||
[$dict.new$(), toList([])],
|
||||
(a, k, v) => {
|
||||
let $1 = a[1];
|
||||
if ($1 instanceof $Empty) {
|
||||
return fold_dict(a, k, v, key.function, value.function);
|
||||
} else {
|
||||
return a;
|
||||
}
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return [$dict.new$(), decode_error("Dict", data)];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes lists where all elements are decoded with a given
|
||||
* decoder.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let result =
|
||||
* [1, 2, 3]
|
||||
* |> list.map(dynamic.int)
|
||||
* |> dynamic.list
|
||||
* |> decode.run(decode.list(of: decode.int))
|
||||
* assert result == Ok([1, 2, 3])
|
||||
* ```
|
||||
*/
|
||||
export function list(inner) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
return decode_list(
|
||||
data,
|
||||
inner.function,
|
||||
(p, k) => { return push_path(p, toList([k])); },
|
||||
0,
|
||||
toList([]),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function push_path(layer, path) {
|
||||
let decoder = one_of(
|
||||
string,
|
||||
toList([
|
||||
(() => {
|
||||
let _pipe = int;
|
||||
return map(_pipe, $int.to_string);
|
||||
})(),
|
||||
]),
|
||||
);
|
||||
let path$1 = $list.map(
|
||||
path,
|
||||
(key) => {
|
||||
let key$1 = cast(key);
|
||||
let $ = run(key$1, decoder);
|
||||
if ($ instanceof Ok) {
|
||||
let key$2 = $[0];
|
||||
return key$2;
|
||||
} else {
|
||||
return ("<" + $dynamic.classify(key$1)) + ">";
|
||||
}
|
||||
},
|
||||
);
|
||||
let errors = $list.map(
|
||||
layer[1],
|
||||
(error) => {
|
||||
return new DecodeError(
|
||||
error.expected,
|
||||
error.found,
|
||||
$list.append(path$1, error.path),
|
||||
);
|
||||
},
|
||||
);
|
||||
return [layer[0], errors];
|
||||
}
|
||||
|
||||
function index(
|
||||
loop$path,
|
||||
loop$position,
|
||||
loop$inner,
|
||||
loop$data,
|
||||
loop$handle_miss
|
||||
) {
|
||||
while (true) {
|
||||
let path = loop$path;
|
||||
let position = loop$position;
|
||||
let inner = loop$inner;
|
||||
let data = loop$data;
|
||||
let handle_miss = loop$handle_miss;
|
||||
if (path instanceof $Empty) {
|
||||
let _pipe = data;
|
||||
let _pipe$1 = inner(_pipe);
|
||||
return push_path(_pipe$1, $list.reverse(position));
|
||||
} else {
|
||||
let key = path.head;
|
||||
let path$1 = path.tail;
|
||||
let $ = bare_index(data, key);
|
||||
if ($ instanceof Ok) {
|
||||
let $1 = $[0];
|
||||
if ($1 instanceof Some) {
|
||||
let data$1 = $1[0];
|
||||
loop$path = path$1;
|
||||
loop$position = listPrepend(key, position);
|
||||
loop$inner = inner;
|
||||
loop$data = data$1;
|
||||
loop$handle_miss = handle_miss;
|
||||
} else {
|
||||
return handle_miss(data, listPrepend(key, position));
|
||||
}
|
||||
} else {
|
||||
let kind = $[0];
|
||||
let $1 = inner(data);
|
||||
let default$;
|
||||
default$ = $1[0];
|
||||
let _pipe = [
|
||||
default$,
|
||||
toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]),
|
||||
];
|
||||
return push_path(_pipe, $list.reverse(position));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as [`field`](#field), except taking a path to the value rather
|
||||
* than a field name.
|
||||
*
|
||||
* This function will index into dictionaries with any key type, and if the key is
|
||||
* an int then it'll also index into Erlang tuples and JavaScript arrays, and
|
||||
* the first eight elements of Gleam lists.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("data"), dynamic.properties([
|
||||
* #(dynamic.string("email"), dynamic.string("lucy@example.com")),
|
||||
* #(dynamic.string("name"), dynamic.string("Lucy")),
|
||||
* ])
|
||||
* ]))
|
||||
*
|
||||
* let decoder = {
|
||||
* use name <- decode.subfield(["data", "name"], decode.string)
|
||||
* use email <- decode.subfield(["data", "email"], decode.string)
|
||||
* decode.success(SignUp(name: name, email: email))
|
||||
* }
|
||||
* let result = decode.run(data, decoder)
|
||||
* assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com"))
|
||||
* ```
|
||||
*/
|
||||
export function subfield(field_path, field_decoder, next) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
let $ = index(
|
||||
field_path,
|
||||
toList([]),
|
||||
field_decoder.function,
|
||||
data,
|
||||
(data, position) => {
|
||||
let $1 = field_decoder.function(data);
|
||||
let default$;
|
||||
default$ = $1[0];
|
||||
let _pipe = [
|
||||
default$,
|
||||
toList([new DecodeError("Field", "Nothing", toList([]))]),
|
||||
];
|
||||
return push_path(_pipe, $list.reverse(position));
|
||||
},
|
||||
);
|
||||
let out;
|
||||
let errors1;
|
||||
out = $[0];
|
||||
errors1 = $[1];
|
||||
let $1 = next(out).function(data);
|
||||
let out$1;
|
||||
let errors2;
|
||||
out$1 = $1[0];
|
||||
errors2 = $1[1];
|
||||
return [out$1, $list.append(errors1, errors2)];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes a value that is nested within other values. For
|
||||
* example, decoding a value that is within some deeply nested JSON objects.
|
||||
*
|
||||
* This function will index into dictionaries with any key type, and if the key is
|
||||
* an int then it'll also index into Erlang tuples and JavaScript arrays, and
|
||||
* the first eight elements of Gleam lists.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = decode.at(["one", "two"], decode.int)
|
||||
*
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("one"), dynamic.properties([
|
||||
* #(dynamic.string("two"), dynamic.int(1000)),
|
||||
* ])),
|
||||
* ]))
|
||||
*
|
||||
*
|
||||
* decode.run(data, decoder)
|
||||
* // -> Ok(1000)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* dynamic.nil()
|
||||
* |> decode.run(decode.optional(decode.int))
|
||||
* // -> Ok(option.None)
|
||||
* ```
|
||||
*/
|
||||
export function at(path, inner) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
return index(
|
||||
path,
|
||||
toList([]),
|
||||
inner.function,
|
||||
data,
|
||||
(data, position) => {
|
||||
let $ = inner.function(data);
|
||||
let default$;
|
||||
default$ = $[0];
|
||||
let _pipe = [
|
||||
default$,
|
||||
toList([new DecodeError("Field", "Nothing", toList([]))]),
|
||||
];
|
||||
return push_path(_pipe, $list.reverse(position));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a decoder on a field of a `Dynamic` value, decoding the value if it is
|
||||
* of the desired type, or returning errors. An error is returned if there is
|
||||
* no field for the specified key.
|
||||
*
|
||||
* This function will index into dictionaries with any key type, and if the key is
|
||||
* an int then it'll also index into Erlang tuples and JavaScript arrays, and
|
||||
* the first eight elements of Gleam lists.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("email"), dynamic.string("lucy@example.com")),
|
||||
* #(dynamic.string("name"), dynamic.string("Lucy")),
|
||||
* ]))
|
||||
*
|
||||
* let decoder = {
|
||||
* use name <- decode.field("name", string)
|
||||
* use email <- decode.field("email", string)
|
||||
* decode.success(SignUp(name: name, email: email))
|
||||
* }
|
||||
*
|
||||
* let result = decode.run(data, decoder)
|
||||
* assert result == Ok(SignUp(name: "Lucy", email: "lucy@example.com"))
|
||||
* ```
|
||||
*
|
||||
* If you wish to decode a value that is more deeply nested within the dynamic
|
||||
* data, see [`subfield`](#subfield) and [`at`](#at).
|
||||
*
|
||||
* If you wish to return a default in the event that a field is not present,
|
||||
* see [`optional_field`](#optional_field) and / [`optionally_at`](#optionally_at).
|
||||
*/
|
||||
export function field(field_name, field_decoder, next) {
|
||||
return subfield(toList([field_name]), field_decoder, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a decoder on a field of a `Dynamic` value, decoding the value if it is
|
||||
* of the desired type, or returning errors. The given default value is
|
||||
* returned if there is no field for the specified key.
|
||||
*
|
||||
* This function will index into dictionaries with any key type, and if the key is
|
||||
* an int then it'll also index into Erlang tuples and JavaScript arrays, and
|
||||
* the first eight elements of Gleam lists.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("name"), dynamic.string("Lucy")),
|
||||
* ]))
|
||||
*
|
||||
* let decoder = {
|
||||
* use name <- decode.field("name", string)
|
||||
* use email <- decode.optional_field("email", "n/a", string)
|
||||
* decode.success(SignUp(name: name, email: email))
|
||||
* }
|
||||
*
|
||||
* let result = decode.run(data, decoder)
|
||||
* assert result == Ok(SignUp(name: "Lucy", email: "n/a"))
|
||||
* ```
|
||||
*/
|
||||
export function optional_field(key, default$, field_decoder, next) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
let _block;
|
||||
let _block$1;
|
||||
let $1 = bare_index(data, key);
|
||||
if ($1 instanceof Ok) {
|
||||
let $2 = $1[0];
|
||||
if ($2 instanceof Some) {
|
||||
let data$1 = $2[0];
|
||||
_block$1 = field_decoder.function(data$1);
|
||||
} else {
|
||||
_block$1 = [default$, toList([])];
|
||||
}
|
||||
} else {
|
||||
let kind = $1[0];
|
||||
_block$1 = [
|
||||
default$,
|
||||
toList([new DecodeError(kind, $dynamic.classify(data), toList([]))]),
|
||||
];
|
||||
}
|
||||
let _pipe = _block$1;
|
||||
_block = push_path(_pipe, toList([key]));
|
||||
let $ = _block;
|
||||
let out;
|
||||
let errors1;
|
||||
out = $[0];
|
||||
errors1 = $[1];
|
||||
let $2 = next(out).function(data);
|
||||
let out$1;
|
||||
let errors2;
|
||||
out$1 = $2[0];
|
||||
errors2 = $2[1];
|
||||
return [out$1, $list.append(errors1, errors2)];
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* A decoder that decodes a value that is nested within other values. For
|
||||
* example, decoding a value that is within some deeply nested JSON objects.
|
||||
*
|
||||
* This function will index into dictionaries with any key type, and if the key is
|
||||
* an int then it'll also index into Erlang tuples and JavaScript arrays, and
|
||||
* the first eight elements of Gleam lists.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* let decoder = decode.optionally_at(["one", "two"], 100, decode.int)
|
||||
*
|
||||
* let data = dynamic.properties([
|
||||
* #(dynamic.string("one"), dynamic.properties([])),
|
||||
* ]))
|
||||
*
|
||||
*
|
||||
* decode.run(data, decoder)
|
||||
* // -> Ok(100)
|
||||
* ```
|
||||
*/
|
||||
export function optionally_at(path, default$, inner) {
|
||||
return new Decoder(
|
||||
(data) => {
|
||||
return index(
|
||||
path,
|
||||
toList([]),
|
||||
inner.function,
|
||||
data,
|
||||
(_, _1) => { return [default$, toList([])]; },
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
553
build/dev/javascript/gleam_stdlib/gleam/float.mjs
Normal file
553
build/dev/javascript/gleam_stdlib/gleam/float.mjs
Normal file
|
|
@ -0,0 +1,553 @@
|
|||
import { Ok, Error, Empty as $Empty, divideFloat } from "../gleam.mjs";
|
||||
import * as $order from "../gleam/order.mjs";
|
||||
import {
|
||||
parse_float as parse,
|
||||
float_to_string as to_string,
|
||||
ceiling,
|
||||
floor,
|
||||
round as js_round,
|
||||
truncate,
|
||||
identity as do_to_float,
|
||||
power as do_power,
|
||||
random_uniform as random,
|
||||
log as do_log,
|
||||
exp as exponential,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export { ceiling, exponential, floor, parse, random, to_string, truncate };
|
||||
|
||||
/**
|
||||
* Compares two `Float`s, returning an `Order`:
|
||||
* `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* compare(2.0, 2.3)
|
||||
* // -> Lt
|
||||
* ```
|
||||
*
|
||||
* To handle
|
||||
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)
|
||||
* you may use [`loosely_compare`](#loosely_compare) instead.
|
||||
*/
|
||||
export function compare(a, b) {
|
||||
let $ = a === b;
|
||||
if ($) {
|
||||
return new $order.Eq();
|
||||
} else {
|
||||
let $1 = a < b;
|
||||
if ($1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
return new $order.Gt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two `Float`s, returning the smaller of the two.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* min(2.0, 2.3)
|
||||
* // -> 2.0
|
||||
* ```
|
||||
*/
|
||||
export function min(a, b) {
|
||||
let $ = a < b;
|
||||
if ($) {
|
||||
return a;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two `Float`s, returning the larger of the two.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* max(2.0, 2.3)
|
||||
* // -> 2.3
|
||||
* ```
|
||||
*/
|
||||
export function max(a, b) {
|
||||
let $ = a > b;
|
||||
if ($) {
|
||||
return a;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts a `Float` between a lower and upper bound.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* clamp(1.2, min: 1.4, max: 1.6)
|
||||
* // -> 1.4
|
||||
* ```
|
||||
*/
|
||||
export function clamp(x, min_bound, max_bound) {
|
||||
let _pipe = x;
|
||||
let _pipe$1 = min(_pipe, max_bound);
|
||||
return max(_pipe$1, min_bound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of the input as a `Float`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* absolute_value(-12.5)
|
||||
* // -> 12.5
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* absolute_value(10.2)
|
||||
* // -> 10.2
|
||||
* ```
|
||||
*/
|
||||
export function absolute_value(x) {
|
||||
let $ = x >= 0.0;
|
||||
if ($) {
|
||||
return x;
|
||||
} else {
|
||||
return 0.0 - x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two `Float`s within a tolerance, returning an `Order`:
|
||||
* `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.
|
||||
*
|
||||
* This function allows Float comparison while handling
|
||||
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).
|
||||
*
|
||||
* Notice: For `Float`s the tolerance won't be exact:
|
||||
* `5.3 - 5.0` is not exactly `0.3`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* loosely_compare(5.0, with: 5.3, tolerating: 0.5)
|
||||
* // -> Eq
|
||||
* ```
|
||||
*
|
||||
* If you want to check only for equality you may use
|
||||
* [`loosely_equals`](#loosely_equals) instead.
|
||||
*/
|
||||
export function loosely_compare(a, b, tolerance) {
|
||||
let difference = absolute_value(a - b);
|
||||
let $ = difference <= tolerance;
|
||||
if ($) {
|
||||
return new $order.Eq();
|
||||
} else {
|
||||
return compare(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for equality of two `Float`s within a tolerance,
|
||||
* returning an `Bool`.
|
||||
*
|
||||
* This function allows Float comparison while handling
|
||||
* [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).
|
||||
*
|
||||
* Notice: For `Float`s the tolerance won't be exact:
|
||||
* `5.3 - 5.0` is not exactly `0.3`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* loosely_equals(5.0, with: 5.3, tolerating: 0.5)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* loosely_equals(5.0, with: 5.1, tolerating: 0.1)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function loosely_equals(a, b, tolerance) {
|
||||
let difference = absolute_value(a - b);
|
||||
return difference <= tolerance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the results of the base being raised to the power of the
|
||||
* exponent, as a `Float`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* power(2.0, -1.0)
|
||||
* // -> Ok(0.5)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(2.0, 2.0)
|
||||
* // -> Ok(4.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(8.0, 1.5)
|
||||
* // -> Ok(22.627416997969522)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 4.0 |> power(of: 2.0)
|
||||
* // -> Ok(16.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(-1.0, 0.5)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function power(base, exponent) {
|
||||
let fractional = (ceiling(exponent) - exponent) > 0.0;
|
||||
let $ = ((base < 0.0) && fractional) || ((base === 0.0) && (exponent < 0.0));
|
||||
if ($) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
return new Ok(do_power(base, exponent));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the input as a `Float`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* square_root(4.0)
|
||||
* // -> Ok(2.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* square_root(-16.0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function square_root(x) {
|
||||
return power(x, 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of the value provided.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* negate(1.0)
|
||||
* // -> -1.0
|
||||
* ```
|
||||
*/
|
||||
export function negate(x) {
|
||||
return -1.0 * x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the value to the nearest whole number as an `Int`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* round(2.3)
|
||||
* // -> 2
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* round(2.5)
|
||||
* // -> 3
|
||||
* ```
|
||||
*/
|
||||
export function round(x) {
|
||||
let $ = x >= 0.0;
|
||||
if ($) {
|
||||
return js_round(x);
|
||||
} else {
|
||||
return 0 - js_round(negate(x));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the value to a given precision as a `Float`.
|
||||
* The precision is the number of allowed decimal places.
|
||||
* Negative precisions are allowed and force rounding
|
||||
* to the nearest tenth, hundredth, thousandth etc.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_precision(2.43434348473, precision: 2)
|
||||
* // -> 2.43
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_precision(547890.453444, precision: -3)
|
||||
* // -> 548000.0
|
||||
* ```
|
||||
*/
|
||||
export function to_precision(x, precision) {
|
||||
let $ = precision <= 0;
|
||||
if ($) {
|
||||
let factor = do_power(10.0, do_to_float(- precision));
|
||||
return do_to_float(round(divideFloat(x, factor))) * factor;
|
||||
} else {
|
||||
let factor = do_power(10.0, do_to_float(precision));
|
||||
return divideFloat(do_to_float(round(x * factor)), factor);
|
||||
}
|
||||
}
|
||||
|
||||
function sum_loop(loop$numbers, loop$initial) {
|
||||
while (true) {
|
||||
let numbers = loop$numbers;
|
||||
let initial = loop$initial;
|
||||
if (numbers instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let first = numbers.head;
|
||||
let rest = numbers.tail;
|
||||
loop$numbers = rest;
|
||||
loop$initial = first + initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums a list of `Float`s.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* ```gleam
|
||||
* sum([1.0, 2.2, 3.3])
|
||||
* // -> 6.5
|
||||
* ```
|
||||
*/
|
||||
export function sum(numbers) {
|
||||
return sum_loop(numbers, 0.0);
|
||||
}
|
||||
|
||||
function product_loop(loop$numbers, loop$initial) {
|
||||
while (true) {
|
||||
let numbers = loop$numbers;
|
||||
let initial = loop$initial;
|
||||
if (numbers instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let first = numbers.head;
|
||||
let rest = numbers.tail;
|
||||
loop$numbers = rest;
|
||||
loop$initial = first * initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies a list of `Float`s and returns the product.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* ```gleam
|
||||
* product([2.5, 3.2, 4.2])
|
||||
* // -> 33.6
|
||||
* ```
|
||||
*/
|
||||
export function product(numbers) {
|
||||
return product_loop(numbers, 1.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the modulo of an float division of inputs as a `Result`.
|
||||
*
|
||||
* Returns division of the inputs as a `Result`: If the given divisor equals
|
||||
* `0`, this function returns an `Error`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(13.3, by: 3.3)
|
||||
* // -> Ok(0.1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(-13.3, by: 3.3)
|
||||
* // -> Ok(3.2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(13.3, by: -3.3)
|
||||
* // -> Ok(-3.2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(-13.3, by: -3.3)
|
||||
* // -> Ok(-0.1)
|
||||
* ```
|
||||
*/
|
||||
export function modulo(dividend, divisor) {
|
||||
if (divisor === 0.0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
return new Ok(dividend - (floor(divideFloat(dividend, divisor)) * divisor));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns division of the inputs as a `Result`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* divide(0.0, 1.0)
|
||||
* // -> Ok(0.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* divide(1.0, 0.0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function divide(a, b) {
|
||||
if (b === 0.0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let b$1 = b;
|
||||
return new Ok(divideFloat(a, b$1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two floats together.
|
||||
*
|
||||
* It's the function equivalent of the `+.` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* add(1.0, 2.0)
|
||||
* // -> 3.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
*
|
||||
* list.fold([1.0, 2.0, 3.0], 0.0, add)
|
||||
* // -> 6.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3.0 |> add(2.0)
|
||||
* // -> 5.0
|
||||
* ```
|
||||
*/
|
||||
export function add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two floats together.
|
||||
*
|
||||
* It's the function equivalent of the `*.` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* multiply(2.0, 4.0)
|
||||
* // -> 8.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
*
|
||||
* list.fold([2.0, 3.0, 4.0], 1.0, multiply)
|
||||
* // -> 24.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3.0 |> multiply(2.0)
|
||||
* // -> 6.0
|
||||
* ```
|
||||
*/
|
||||
export function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts one float from another.
|
||||
*
|
||||
* It's the function equivalent of the `-.` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* subtract(3.0, 1.0)
|
||||
* // -> 2.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
*
|
||||
* list.fold([1.0, 2.0, 3.0], 10.0, subtract)
|
||||
* // -> 4.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3.0 |> subtract(_, 2.0)
|
||||
* // -> 1.0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3.0 |> subtract(2.0, _)
|
||||
* // -> -1.0
|
||||
* ```
|
||||
*/
|
||||
export function subtract(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm (base e) of the given as a `Result`. If the
|
||||
* input is less than or equal to 0, returns `Error(Nil)`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* logarithm(1.0)
|
||||
* // -> Ok(0.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* logarithm(2.718281828459045) // e
|
||||
* // -> Ok(1.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* logarithm(0.0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* logarithm(-1.0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function logarithm(x) {
|
||||
let $ = x <= 0.0;
|
||||
if ($) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
return new Ok(do_log(x));
|
||||
}
|
||||
}
|
||||
17
build/dev/javascript/gleam_stdlib/gleam/function.mjs
Normal file
17
build/dev/javascript/gleam_stdlib/gleam/function.mjs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* Takes a single argument and always returns its input value.
|
||||
*/
|
||||
export function identity(x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an argument and a single function, calls that function with that
|
||||
* argument and returns that argument instead of the function return value.
|
||||
*
|
||||
* Useful for running synchronous side effects in a pipeline.
|
||||
*/
|
||||
export function tap(arg, effect) {
|
||||
effect(arg);
|
||||
return arg;
|
||||
}
|
||||
816
build/dev/javascript/gleam_stdlib/gleam/int.mjs
Normal file
816
build/dev/javascript/gleam_stdlib/gleam/int.mjs
Normal file
|
|
@ -0,0 +1,816 @@
|
|||
import {
|
||||
Ok,
|
||||
Error,
|
||||
toList,
|
||||
Empty as $Empty,
|
||||
prepend as listPrepend,
|
||||
remainderInt,
|
||||
divideInt,
|
||||
} from "../gleam.mjs";
|
||||
import * as $float from "../gleam/float.mjs";
|
||||
import * as $order from "../gleam/order.mjs";
|
||||
import {
|
||||
parse_int as parse,
|
||||
int_from_base_string as do_base_parse,
|
||||
to_string,
|
||||
int_to_base_string as do_to_base_string,
|
||||
identity as to_float,
|
||||
bitwise_and,
|
||||
bitwise_not,
|
||||
bitwise_or,
|
||||
bitwise_exclusive_or,
|
||||
bitwise_shift_left,
|
||||
bitwise_shift_right,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export {
|
||||
bitwise_and,
|
||||
bitwise_exclusive_or,
|
||||
bitwise_not,
|
||||
bitwise_or,
|
||||
bitwise_shift_left,
|
||||
bitwise_shift_right,
|
||||
parse,
|
||||
to_float,
|
||||
to_string,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the absolute value of the input.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* absolute_value(-12)
|
||||
* // -> 12
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* absolute_value(10)
|
||||
* // -> 10
|
||||
* ```
|
||||
*/
|
||||
export function absolute_value(x) {
|
||||
let $ = x >= 0;
|
||||
if ($) {
|
||||
return x;
|
||||
} else {
|
||||
return x * -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a given string as an int in a given base if possible.
|
||||
* Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* base_parse("10", 2)
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* base_parse("30", 16)
|
||||
* // -> Ok(48)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* base_parse("1C", 36)
|
||||
* // -> Ok(48)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* base_parse("48", 1)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* base_parse("48", 37)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function base_parse(string, base) {
|
||||
let $ = (base >= 2) && (base <= 36);
|
||||
if ($) {
|
||||
return do_base_parse(string, base);
|
||||
} else {
|
||||
return new Error(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a given int to a string using the base number provided.
|
||||
* Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.
|
||||
* For common bases (2, 8, 16, 36), use the `to_baseN` functions.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_base_string(2, 2)
|
||||
* // -> Ok("10")
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_base_string(48, 16)
|
||||
* // -> Ok("30")
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_base_string(48, 36)
|
||||
* // -> Ok("1C")
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_base_string(48, 1)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_base_string(48, 37)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function to_base_string(x, base) {
|
||||
let $ = (base >= 2) && (base <= 36);
|
||||
if ($) {
|
||||
return new Ok(do_to_base_string(x, base));
|
||||
} else {
|
||||
return new Error(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a given int to a string using base-2.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_base2(2)
|
||||
* // -> "10"
|
||||
* ```
|
||||
*/
|
||||
export function to_base2(x) {
|
||||
return do_to_base_string(x, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a given int to a string using base-8.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_base8(15)
|
||||
* // -> "17"
|
||||
* ```
|
||||
*/
|
||||
export function to_base8(x) {
|
||||
return do_to_base_string(x, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a given int to a string using base-16.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_base16(48)
|
||||
* // -> "30"
|
||||
* ```
|
||||
*/
|
||||
export function to_base16(x) {
|
||||
return do_to_base_string(x, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a given int to a string using base-36.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_base36(48)
|
||||
* // -> "1C"
|
||||
* ```
|
||||
*/
|
||||
export function to_base36(x) {
|
||||
return do_to_base_string(x, 36);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the results of the base being raised to the power of the
|
||||
* exponent, as a `Float`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* power(2, -1.0)
|
||||
* // -> Ok(0.5)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(2, 2.0)
|
||||
* // -> Ok(4.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(8, 1.5)
|
||||
* // -> Ok(22.627416997969522)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 4 |> power(of: 2.0)
|
||||
* // -> Ok(16.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* power(-1, 0.5)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function power(base, exponent) {
|
||||
let _pipe = base;
|
||||
let _pipe$1 = to_float(_pipe);
|
||||
return $float.power(_pipe$1, exponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the input as a `Float`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* square_root(4)
|
||||
* // -> Ok(2.0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* square_root(-16)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function square_root(x) {
|
||||
let _pipe = x;
|
||||
let _pipe$1 = to_float(_pipe);
|
||||
return $float.square_root(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two ints, returning an order.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* compare(2, 3)
|
||||
* // -> Lt
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* compare(4, 3)
|
||||
* // -> Gt
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* compare(3, 3)
|
||||
* // -> Eq
|
||||
* ```
|
||||
*/
|
||||
export function compare(a, b) {
|
||||
let $ = a === b;
|
||||
if ($) {
|
||||
return new $order.Eq();
|
||||
} else {
|
||||
let $1 = a < b;
|
||||
if ($1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
return new $order.Gt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two ints, returning the smaller of the two.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* min(2, 3)
|
||||
* // -> 2
|
||||
* ```
|
||||
*/
|
||||
export function min(a, b) {
|
||||
let $ = a < b;
|
||||
if ($) {
|
||||
return a;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two ints, returning the larger of the two.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* max(2, 3)
|
||||
* // -> 3
|
||||
* ```
|
||||
*/
|
||||
export function max(a, b) {
|
||||
let $ = a > b;
|
||||
if ($) {
|
||||
return a;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restricts an int between a lower and upper bound.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* clamp(40, min: 50, max: 60)
|
||||
* // -> 50
|
||||
* ```
|
||||
*/
|
||||
export function clamp(x, min_bound, max_bound) {
|
||||
let _pipe = x;
|
||||
let _pipe$1 = min(_pipe, max_bound);
|
||||
return max(_pipe$1, min_bound);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the value provided is even.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_even(2)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_even(3)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_even(x) {
|
||||
return (x % 2) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the value provided is odd.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_odd(3)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_odd(2)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_odd(x) {
|
||||
return (x % 2) !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negative of the value provided.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* negate(1)
|
||||
* // -> -1
|
||||
* ```
|
||||
*/
|
||||
export function negate(x) {
|
||||
return -1 * x;
|
||||
}
|
||||
|
||||
function sum_loop(loop$numbers, loop$initial) {
|
||||
while (true) {
|
||||
let numbers = loop$numbers;
|
||||
let initial = loop$initial;
|
||||
if (numbers instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let first = numbers.head;
|
||||
let rest = numbers.tail;
|
||||
loop$numbers = rest;
|
||||
loop$initial = first + initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sums a list of ints.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* ```gleam
|
||||
* sum([1, 2, 3])
|
||||
* // -> 6
|
||||
* ```
|
||||
*/
|
||||
export function sum(numbers) {
|
||||
return sum_loop(numbers, 0);
|
||||
}
|
||||
|
||||
function product_loop(loop$numbers, loop$initial) {
|
||||
while (true) {
|
||||
let numbers = loop$numbers;
|
||||
let initial = loop$initial;
|
||||
if (numbers instanceof $Empty) {
|
||||
return initial;
|
||||
} else {
|
||||
let first = numbers.head;
|
||||
let rest = numbers.tail;
|
||||
loop$numbers = rest;
|
||||
loop$initial = first * initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies a list of ints and returns the product.
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* ```gleam
|
||||
* product([2, 3, 4])
|
||||
* // -> 24
|
||||
* ```
|
||||
*/
|
||||
export function product(numbers) {
|
||||
return product_loop(numbers, 1);
|
||||
}
|
||||
|
||||
function digits_loop(loop$x, loop$base, loop$acc) {
|
||||
while (true) {
|
||||
let x = loop$x;
|
||||
let base = loop$base;
|
||||
let acc = loop$acc;
|
||||
let $ = absolute_value(x) < base;
|
||||
if ($) {
|
||||
return listPrepend(x, acc);
|
||||
} else {
|
||||
loop$x = divideInt(x, base);
|
||||
loop$base = base;
|
||||
loop$acc = listPrepend(remainderInt(x, base), acc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function digits(x, base) {
|
||||
let $ = base < 2;
|
||||
if ($) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
return new Ok(digits_loop(x, base, toList([])));
|
||||
}
|
||||
}
|
||||
|
||||
function undigits_loop(loop$numbers, loop$base, loop$acc) {
|
||||
while (true) {
|
||||
let numbers = loop$numbers;
|
||||
let base = loop$base;
|
||||
let acc = loop$acc;
|
||||
if (numbers instanceof $Empty) {
|
||||
return new Ok(acc);
|
||||
} else {
|
||||
let digit = numbers.head;
|
||||
if (digit >= base) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let digit$1 = numbers.head;
|
||||
let rest = numbers.tail;
|
||||
loop$numbers = rest;
|
||||
loop$base = base;
|
||||
loop$acc = acc * base + digit$1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function undigits(numbers, base) {
|
||||
let $ = base < 2;
|
||||
if ($) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
return undigits_loop(numbers, base, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random int between zero and the given maximum.
|
||||
*
|
||||
* The lower number is inclusive, the upper number is exclusive.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* random(10)
|
||||
* // -> 4
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* random(1)
|
||||
* // -> 0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* random(-1)
|
||||
* // -> -1
|
||||
* ```
|
||||
*/
|
||||
export function random(max) {
|
||||
let _pipe = ($float.random() * to_float(max));
|
||||
let _pipe$1 = $float.floor(_pipe);
|
||||
return $float.round(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a truncated integer division.
|
||||
*
|
||||
* Returns division of the inputs as a `Result`: If the given divisor equals
|
||||
* `0`, this function returns an `Error`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* divide(0, 1)
|
||||
* // -> Ok(0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* divide(1, 0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* divide(5, 2)
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* divide(-99, 2)
|
||||
* // -> Ok(-49)
|
||||
* ```
|
||||
*/
|
||||
export function divide(dividend, divisor) {
|
||||
if (divisor === 0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let divisor$1 = divisor;
|
||||
return new Ok(divideInt(dividend, divisor$1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the remainder of an integer division of inputs as a `Result`.
|
||||
*
|
||||
* Returns division of the inputs as a `Result`: If the given divisor equals
|
||||
* `0`, this function returns an `Error`.
|
||||
*
|
||||
* Most the time you will want to use the `%` operator instead of this
|
||||
* function.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(3, 2)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(1, 0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(10, -1)
|
||||
* // -> Ok(0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(13, by: 3)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(-13, by: 3)
|
||||
* // -> Ok(-1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(13, by: -3)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* remainder(-13, by: -3)
|
||||
* // -> Ok(-1)
|
||||
* ```
|
||||
*/
|
||||
export function remainder(dividend, divisor) {
|
||||
if (divisor === 0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let divisor$1 = divisor;
|
||||
return new Ok(remainderInt(dividend, divisor$1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the modulo of an integer division of inputs as a `Result`.
|
||||
*
|
||||
* Returns division of the inputs as a `Result`: If the given divisor equals
|
||||
* `0`, this function returns an `Error`.
|
||||
*
|
||||
* Most the time you will want to use the `%` operator instead of this
|
||||
* function.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(3, 2)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(1, 0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(10, -1)
|
||||
* // -> Ok(0)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(13, by: 3)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* modulo(-13, by: 3)
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*/
|
||||
export function modulo(dividend, divisor) {
|
||||
if (divisor === 0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let remainder$1 = remainderInt(dividend, divisor);
|
||||
let $ = remainder$1 * divisor < 0;
|
||||
if ($) {
|
||||
return new Ok(remainder$1 + divisor);
|
||||
} else {
|
||||
return new Ok(remainder$1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a *floored* integer division, which means that the result will
|
||||
* always be rounded towards negative infinity.
|
||||
*
|
||||
* If you want to perform truncated integer division (rounding towards zero),
|
||||
* use `int.divide()` or the `/` operator instead.
|
||||
*
|
||||
* Returns division of the inputs as a `Result`: If the given divisor equals
|
||||
* `0`, this function returns an `Error`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* floor_divide(1, 0)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* floor_divide(5, 2)
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* floor_divide(6, -4)
|
||||
* // -> Ok(-2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* floor_divide(-99, 2)
|
||||
* // -> Ok(-50)
|
||||
* ```
|
||||
*/
|
||||
export function floor_divide(dividend, divisor) {
|
||||
if (divisor === 0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let divisor$1 = divisor;
|
||||
let $ = (dividend * divisor$1 < 0) && ((remainderInt(dividend, divisor$1)) !== 0);
|
||||
if ($) {
|
||||
return new Ok((divideInt(dividend, divisor$1)) - 1);
|
||||
} else {
|
||||
return new Ok(divideInt(dividend, divisor$1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two integers together.
|
||||
*
|
||||
* It's the function equivalent of the `+` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* add(1, 2)
|
||||
* // -> 3
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
* list.fold([1, 2, 3], 0, add)
|
||||
* // -> 6
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3 |> add(2)
|
||||
* // -> 5
|
||||
* ```
|
||||
*/
|
||||
export function add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two integers together.
|
||||
*
|
||||
* It's the function equivalent of the `*` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* multiply(2, 4)
|
||||
* // -> 8
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
*
|
||||
* list.fold([2, 3, 4], 1, multiply)
|
||||
* // -> 24
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3 |> multiply(2)
|
||||
* // -> 6
|
||||
* ```
|
||||
*/
|
||||
export function multiply(a, b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts one int from another.
|
||||
*
|
||||
* It's the function equivalent of the `-` operator.
|
||||
* This function is useful in higher order functions or pipes.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* subtract(3, 1)
|
||||
* // -> 2
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/list
|
||||
*
|
||||
* list.fold([1, 2, 3], 10, subtract)
|
||||
* // -> 4
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3 |> subtract(2)
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* 3 |> subtract(2, _)
|
||||
* // -> -1
|
||||
* ```
|
||||
*/
|
||||
export function subtract(a, b) {
|
||||
return a - b;
|
||||
}
|
||||
8
build/dev/javascript/gleam_stdlib/gleam/io.mjs
Normal file
8
build/dev/javascript/gleam_stdlib/gleam/io.mjs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import {
|
||||
print,
|
||||
print_error,
|
||||
console_log as println,
|
||||
console_error as println_error,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export { print, print_error, println, println_error };
|
||||
3209
build/dev/javascript/gleam_stdlib/gleam/list.mjs
Normal file
3209
build/dev/javascript/gleam_stdlib/gleam/list.mjs
Normal file
File diff suppressed because it is too large
Load diff
419
build/dev/javascript/gleam_stdlib/gleam/option.mjs
Normal file
419
build/dev/javascript/gleam_stdlib/gleam/option.mjs
Normal file
|
|
@ -0,0 +1,419 @@
|
|||
import {
|
||||
Ok,
|
||||
Error,
|
||||
toList,
|
||||
Empty as $Empty,
|
||||
prepend as listPrepend,
|
||||
CustomType as $CustomType,
|
||||
isEqual,
|
||||
} from "../gleam.mjs";
|
||||
|
||||
export class Some extends $CustomType {
|
||||
constructor($0) {
|
||||
super();
|
||||
this[0] = $0;
|
||||
}
|
||||
}
|
||||
export const Option$Some = ($0) => new Some($0);
|
||||
export const Option$isSome = (value) => value instanceof Some;
|
||||
export const Option$Some$0 = (value) => value[0];
|
||||
|
||||
export class None extends $CustomType {}
|
||||
export const Option$None = () => new None();
|
||||
export const Option$isNone = (value) => value instanceof None;
|
||||
|
||||
function reverse_and_prepend(loop$prefix, loop$suffix) {
|
||||
while (true) {
|
||||
let prefix = loop$prefix;
|
||||
let suffix = loop$suffix;
|
||||
if (prefix instanceof $Empty) {
|
||||
return suffix;
|
||||
} else {
|
||||
let first = prefix.head;
|
||||
let rest = prefix.tail;
|
||||
loop$prefix = rest;
|
||||
loop$suffix = listPrepend(first, suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function reverse(list) {
|
||||
return reverse_and_prepend(list, toList([]));
|
||||
}
|
||||
|
||||
function all_loop(loop$list, loop$acc) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let acc = loop$acc;
|
||||
if (list instanceof $Empty) {
|
||||
return new Some(reverse(acc));
|
||||
} else {
|
||||
let $ = list.head;
|
||||
if ($ instanceof Some) {
|
||||
let rest = list.tail;
|
||||
let first = $[0];
|
||||
loop$list = rest;
|
||||
loop$acc = listPrepend(first, acc);
|
||||
} else {
|
||||
return new None();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a list of `Option`s into a single `Option`.
|
||||
* If all elements in the list are `Some` then returns a `Some` holding the list of values.
|
||||
* If any element is `None` then returns`None`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* all([Some(1), Some(2)])
|
||||
* // -> Some([1, 2])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* all([Some(1), None])
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function all(list) {
|
||||
return all_loop(list, toList([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the `Option` is a `Some` value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_some(Some(1))
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_some(None)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_some(option) {
|
||||
return !isEqual(option, new None());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the `Option` is a `None` value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_none(Some(1))
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_none(None)
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function is_none(option) {
|
||||
return isEqual(option, new None());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an `Option` type to a `Result` type.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_result(Some(1), "some_error")
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_result(None, "some_error")
|
||||
* // -> Error("some_error")
|
||||
* ```
|
||||
*/
|
||||
export function to_result(option, e) {
|
||||
if (option instanceof Some) {
|
||||
let a = option[0];
|
||||
return new Ok(a);
|
||||
} else {
|
||||
return new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `Result` type to an `Option` type.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_result(Ok(1))
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_result(Error("some_error"))
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function from_result(result) {
|
||||
if (result instanceof Ok) {
|
||||
let a = result[0];
|
||||
return new Some(a);
|
||||
} else {
|
||||
return new None();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the value from an `Option`, returning a default value if there is none.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap(Some(1), 0)
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap(None, 0)
|
||||
* // -> 0
|
||||
* ```
|
||||
*/
|
||||
export function unwrap(option, default$) {
|
||||
if (option instanceof Some) {
|
||||
let x = option[0];
|
||||
return x;
|
||||
} else {
|
||||
return default$;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the value from an `Option`, evaluating the default function if the option is `None`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_unwrap(Some(1), fn() { 0 })
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_unwrap(None, fn() { 0 })
|
||||
* // -> 0
|
||||
* ```
|
||||
*/
|
||||
export function lazy_unwrap(option, default$) {
|
||||
if (option instanceof Some) {
|
||||
let x = option[0];
|
||||
return x;
|
||||
} else {
|
||||
return default$();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a value held within the `Some` of an `Option` by calling a given function
|
||||
* on it.
|
||||
*
|
||||
* If the `Option` is a `None` rather than `Some`, the function is not called and the
|
||||
* `Option` stays the same.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* map(over: Some(1), with: fn(x) { x + 1 })
|
||||
* // -> Some(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* map(over: None, with: fn(x) { x + 1 })
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function map(option, fun) {
|
||||
if (option instanceof Some) {
|
||||
let x = option[0];
|
||||
return new Some(fun(x));
|
||||
} else {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a nested `Option` into a single layer.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(Some(Some(1)))
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(Some(None))
|
||||
* // -> None
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(None)
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function flatten(option) {
|
||||
if (option instanceof Some) {
|
||||
let x = option[0];
|
||||
return x;
|
||||
} else {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a value held within the `Some` of an `Option` by calling a given function
|
||||
* on it, where the given function also returns an `Option`. The two options are
|
||||
* then merged together into one `Option`.
|
||||
*
|
||||
* If the `Option` is a `None` rather than `Some` the function is not called and the
|
||||
* option stays the same.
|
||||
*
|
||||
* This function is the equivalent of calling `map` followed by `flatten`, and
|
||||
* it is useful for chaining together multiple functions that return `Option`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* then(Some(1), fn(x) { Some(x + 1) })
|
||||
* // -> Some(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* then(Some(1), fn(x) { Some(#("a", x)) })
|
||||
* // -> Some(#("a", 1))
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* then(Some(1), fn(_) { None })
|
||||
* // -> None
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* then(None, fn(x) { Some(x + 1) })
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function then$(option, fun) {
|
||||
if (option instanceof Some) {
|
||||
let x = option[0];
|
||||
return fun(x);
|
||||
} else {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value if it is `Some`, otherwise returns the second value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* or(Some(1), Some(2))
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(Some(1), None)
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(None, Some(2))
|
||||
* // -> Some(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(None, None)
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function or(first, second) {
|
||||
if (first instanceof Some) {
|
||||
return first;
|
||||
} else {
|
||||
return second;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Some(1), fn() { Some(2) })
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Some(1), fn() { None })
|
||||
* // -> Some(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(None, fn() { Some(2) })
|
||||
* // -> Some(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(None, fn() { None })
|
||||
* // -> None
|
||||
* ```
|
||||
*/
|
||||
export function lazy_or(first, second) {
|
||||
if (first instanceof Some) {
|
||||
return first;
|
||||
} else {
|
||||
return second();
|
||||
}
|
||||
}
|
||||
|
||||
function values_loop(loop$list, loop$acc) {
|
||||
while (true) {
|
||||
let list = loop$list;
|
||||
let acc = loop$acc;
|
||||
if (list instanceof $Empty) {
|
||||
return reverse(acc);
|
||||
} else {
|
||||
let $ = list.head;
|
||||
if ($ instanceof Some) {
|
||||
let rest = list.tail;
|
||||
let first = $[0];
|
||||
loop$list = rest;
|
||||
loop$acc = listPrepend(first, acc);
|
||||
} else {
|
||||
let rest = list.tail;
|
||||
loop$list = rest;
|
||||
loop$acc = acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of `Option`s,
|
||||
* returns only the values inside `Some`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* values([Some(1), None, Some(3)])
|
||||
* // -> [1, 3]
|
||||
* ```
|
||||
*/
|
||||
export function values(options) {
|
||||
return values_loop(options, toList([]));
|
||||
}
|
||||
178
build/dev/javascript/gleam_stdlib/gleam/order.mjs
Normal file
178
build/dev/javascript/gleam_stdlib/gleam/order.mjs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
import { CustomType as $CustomType, isEqual } from "../gleam.mjs";
|
||||
|
||||
export class Lt extends $CustomType {}
|
||||
export const Order$Lt = () => new Lt();
|
||||
export const Order$isLt = (value) => value instanceof Lt;
|
||||
|
||||
export class Eq extends $CustomType {}
|
||||
export const Order$Eq = () => new Eq();
|
||||
export const Order$isEq = (value) => value instanceof Eq;
|
||||
|
||||
export class Gt extends $CustomType {}
|
||||
export const Order$Gt = () => new Gt();
|
||||
export const Order$isGt = (value) => value instanceof Gt;
|
||||
|
||||
/**
|
||||
* Inverts an order, so less-than becomes greater-than and greater-than
|
||||
* becomes less-than.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* negate(Lt)
|
||||
* // -> Gt
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* negate(Eq)
|
||||
* // -> Eq
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* negate(Gt)
|
||||
* // -> Lt
|
||||
* ```
|
||||
*/
|
||||
export function negate(order) {
|
||||
if (order instanceof Lt) {
|
||||
return new Gt();
|
||||
} else if (order instanceof Eq) {
|
||||
return order;
|
||||
} else {
|
||||
return new Lt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a numeric representation of the order.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_int(Lt)
|
||||
* // -> -1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_int(Eq)
|
||||
* // -> 0
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_int(Gt)
|
||||
* // -> 1
|
||||
* ```
|
||||
*/
|
||||
export function to_int(order) {
|
||||
if (order instanceof Lt) {
|
||||
return -1;
|
||||
} else if (order instanceof Eq) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two `Order` values to one another, producing a new `Order`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* compare(Eq, with: Lt)
|
||||
* // -> Gt
|
||||
* ```
|
||||
*/
|
||||
export function compare(a, b) {
|
||||
let x = a;
|
||||
let y = b;
|
||||
if (isEqual(x, y)) {
|
||||
return new Eq();
|
||||
} else if (a instanceof Lt) {
|
||||
return new Lt();
|
||||
} else if (a instanceof Eq && b instanceof Gt) {
|
||||
return new Lt();
|
||||
} else {
|
||||
return new Gt();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverts an ordering function, so less-than becomes greater-than and greater-than
|
||||
* becomes less-than.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
* import gleam/list
|
||||
*
|
||||
* list.sort([1, 5, 4], by: reverse(int.compare))
|
||||
* // -> [5, 4, 1]
|
||||
* ```
|
||||
*/
|
||||
export function reverse(orderer) {
|
||||
return (a, b) => { return orderer(b, a); };
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a fallback `Order` in case the first argument is `Eq`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* break_tie(in: int.compare(1, 1), with: Lt)
|
||||
* // -> Lt
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* break_tie(in: int.compare(1, 0), with: Eq)
|
||||
* // -> Gt
|
||||
* ```
|
||||
*/
|
||||
export function break_tie(order, other) {
|
||||
if (order instanceof Lt) {
|
||||
return order;
|
||||
} else if (order instanceof Eq) {
|
||||
return other;
|
||||
} else {
|
||||
return order;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes a fallback function returning an `Order` in case the first argument
|
||||
* is `Eq`.
|
||||
*
|
||||
* This can be useful when the fallback comparison might be expensive and it
|
||||
* needs to be delayed until strictly necessary.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt })
|
||||
* // -> Lt
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq })
|
||||
* // -> Gt
|
||||
* ```
|
||||
*/
|
||||
export function lazy_break_tie(order, comparison) {
|
||||
if (order instanceof Lt) {
|
||||
return order;
|
||||
} else if (order instanceof Eq) {
|
||||
return comparison();
|
||||
} else {
|
||||
return order;
|
||||
}
|
||||
}
|
||||
102
build/dev/javascript/gleam_stdlib/gleam/pair.mjs
Normal file
102
build/dev/javascript/gleam_stdlib/gleam/pair.mjs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Returns the first element in a pair.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* first(#(1, 2))
|
||||
* // -> 1
|
||||
* ```
|
||||
*/
|
||||
export function first(pair) {
|
||||
let a;
|
||||
a = pair[0];
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the second element in a pair.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* second(#(1, 2))
|
||||
* // -> 2
|
||||
* ```
|
||||
*/
|
||||
export function second(pair) {
|
||||
let a;
|
||||
a = pair[1];
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new pair with the elements swapped.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* swap(#(1, 2))
|
||||
* // -> #(2, 1)
|
||||
* ```
|
||||
*/
|
||||
export function swap(pair) {
|
||||
let a;
|
||||
let b;
|
||||
a = pair[0];
|
||||
b = pair[1];
|
||||
return [b, a];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new pair with the first element having had `with` applied to
|
||||
* it.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* #(1, 2) |> map_first(fn(n) { n * 2 })
|
||||
* // -> #(2, 2)
|
||||
* ```
|
||||
*/
|
||||
export function map_first(pair, fun) {
|
||||
let a;
|
||||
let b;
|
||||
a = pair[0];
|
||||
b = pair[1];
|
||||
return [fun(a), b];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new pair with the second element having had `with` applied to
|
||||
* it.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* #(1, 2) |> map_second(fn(n) { n * 2 })
|
||||
* // -> #(1, 4)
|
||||
* ```
|
||||
*/
|
||||
export function map_second(pair, fun) {
|
||||
let a;
|
||||
let b;
|
||||
a = pair[0];
|
||||
b = pair[1];
|
||||
return [a, fun(b)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new pair with the given elements. This can also be done using the dedicated
|
||||
* syntax instead: `new(1, 2) == #(1, 2)`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new(1, 2)
|
||||
* // -> #(1, 2)
|
||||
* ```
|
||||
*/
|
||||
export function new$(first, second) {
|
||||
return [first, second];
|
||||
}
|
||||
494
build/dev/javascript/gleam_stdlib/gleam/result.mjs
Normal file
494
build/dev/javascript/gleam_stdlib/gleam/result.mjs
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
import { Ok, Error, toList, Empty as $Empty, prepend as listPrepend } from "../gleam.mjs";
|
||||
import * as $list from "../gleam/list.mjs";
|
||||
|
||||
/**
|
||||
* Checks whether the result is an `Ok` value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_ok(Ok(1))
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_ok(Error(Nil))
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_ok(result) {
|
||||
if (result instanceof Ok) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the result is an `Error` value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_error(Ok(1))
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_error(Error(Nil))
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function is_error(result) {
|
||||
if (result instanceof Ok) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a value held within the `Ok` of a result by calling a given function
|
||||
* on it.
|
||||
*
|
||||
* If the result is an `Error` rather than `Ok` the function is not called and the
|
||||
* result stays the same.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* map(over: Ok(1), with: fn(x) { x + 1 })
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* map(over: Error(1), with: fn(x) { x + 1 })
|
||||
* // -> Error(1)
|
||||
* ```
|
||||
*/
|
||||
export function map(result, fun) {
|
||||
if (result instanceof Ok) {
|
||||
let x = result[0];
|
||||
return new Ok(fun(x));
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a value held within the `Error` of a result by calling a given function
|
||||
* on it.
|
||||
*
|
||||
* If the result is `Ok` rather than `Error` the function is not called and the
|
||||
* result stays the same.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* map_error(over: Error(1), with: fn(x) { x + 1 })
|
||||
* // -> Error(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* map_error(over: Ok(1), with: fn(x) { x + 1 })
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*/
|
||||
export function map_error(result, fun) {
|
||||
if (result instanceof Ok) {
|
||||
return result;
|
||||
} else {
|
||||
let error = result[0];
|
||||
return new Error(fun(error));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a nested `Result` into a single layer.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(Ok(Ok(1)))
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(Ok(Error("")))
|
||||
* // -> Error("")
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* flatten(Error(Nil))
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function flatten(result) {
|
||||
if (result instanceof Ok) {
|
||||
let x = result[0];
|
||||
return x;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Updates" an `Ok` result by passing its value to a function that yields a result,
|
||||
* and returning the yielded result. (This may "replace" the `Ok` with an `Error`.)
|
||||
*
|
||||
* If the input is an `Error` rather than an `Ok`, the function is not called and
|
||||
* the original `Error` is returned.
|
||||
*
|
||||
* This function is the equivalent of calling `map` followed by `flatten`, and
|
||||
* it is useful for chaining together multiple functions that may fail.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* try(Ok(1), fn(x) { Ok(x + 1) })
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* try(Ok(1), fn(x) { Ok(#("a", x)) })
|
||||
* // -> Ok(#("a", 1))
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* try(Ok(1), fn(_) { Error("Oh no") })
|
||||
* // -> Error("Oh no")
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* try(Error(Nil), fn(x) { Ok(x + 1) })
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*/
|
||||
export function try$(result, fun) {
|
||||
if (result instanceof Ok) {
|
||||
let x = result[0];
|
||||
return fun(x);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export function then$(result, fun) {
|
||||
return try$(result, fun);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the `Ok` value from a result, returning a default value if the result
|
||||
* is an `Error`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap(Ok(1), 0)
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap(Error(""), 0)
|
||||
* // -> 0
|
||||
* ```
|
||||
*/
|
||||
export function unwrap(result, default$) {
|
||||
if (result instanceof Ok) {
|
||||
let v = result[0];
|
||||
return v;
|
||||
} else {
|
||||
return default$;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the `Ok` value from a result, evaluating the default function if the result
|
||||
* is an `Error`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_unwrap(Ok(1), fn() { 0 })
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_unwrap(Error(""), fn() { 0 })
|
||||
* // -> 0
|
||||
* ```
|
||||
*/
|
||||
export function lazy_unwrap(result, default$) {
|
||||
if (result instanceof Ok) {
|
||||
let v = result[0];
|
||||
return v;
|
||||
} else {
|
||||
return default$();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the `Error` value from a result, returning a default value if the result
|
||||
* is an `Ok`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap_error(Error(1), 0)
|
||||
* // -> 1
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* unwrap_error(Ok(""), 0)
|
||||
* // -> 0
|
||||
* ```
|
||||
*/
|
||||
export function unwrap_error(result, default$) {
|
||||
if (result instanceof Ok) {
|
||||
return default$;
|
||||
} else {
|
||||
let e = result[0];
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
export function unwrap_both(result) {
|
||||
if (result instanceof Ok) {
|
||||
let a = result[0];
|
||||
return a;
|
||||
} else {
|
||||
let a = result[0];
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value if it is `Ok`, otherwise returns the second value.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* or(Ok(1), Ok(2))
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(Ok(1), Error("Error 2"))
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(Error("Error 1"), Ok(2))
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* or(Error("Error 1"), Error("Error 2"))
|
||||
* // -> Error("Error 2")
|
||||
* ```
|
||||
*/
|
||||
export function or(first, second) {
|
||||
if (first instanceof Ok) {
|
||||
return first;
|
||||
} else {
|
||||
return second;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value.
|
||||
*
|
||||
* If you need access to the initial error value, use `result.try_recover`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Ok(1), fn() { Ok(2) })
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Ok(1), fn() { Error("Error 2") })
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Error("Error 1"), fn() { Ok(2) })
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* lazy_or(Error("Error 1"), fn() { Error("Error 2") })
|
||||
* // -> Error("Error 2")
|
||||
* ```
|
||||
*/
|
||||
export function lazy_or(first, second) {
|
||||
if (first instanceof Ok) {
|
||||
return first;
|
||||
} else {
|
||||
return second();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines a list of results into a single result.
|
||||
* If all elements in the list are `Ok` then returns an `Ok` holding the list of values.
|
||||
* If any element is `Error` then returns the first error.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* all([Ok(1), Ok(2)])
|
||||
* // -> Ok([1, 2])
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* all([Ok(1), Error("e")])
|
||||
* // -> Error("e")
|
||||
* ```
|
||||
*/
|
||||
export function all(results) {
|
||||
return $list.try_map(results, (result) => { return result; });
|
||||
}
|
||||
|
||||
function partition_loop(loop$results, loop$oks, loop$errors) {
|
||||
while (true) {
|
||||
let results = loop$results;
|
||||
let oks = loop$oks;
|
||||
let errors = loop$errors;
|
||||
if (results instanceof $Empty) {
|
||||
return [oks, errors];
|
||||
} else {
|
||||
let $ = results.head;
|
||||
if ($ instanceof Ok) {
|
||||
let rest = results.tail;
|
||||
let a = $[0];
|
||||
loop$results = rest;
|
||||
loop$oks = listPrepend(a, oks);
|
||||
loop$errors = errors;
|
||||
} else {
|
||||
let rest = results.tail;
|
||||
let e = $[0];
|
||||
loop$results = rest;
|
||||
loop$oks = oks;
|
||||
loop$errors = listPrepend(e, errors);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of results, returns a pair where the first element is a list
|
||||
* of all the values inside `Ok` and the second element is a list with all the
|
||||
* values inside `Error`. The values in both lists appear in reverse order with
|
||||
* respect to their position in the original list of results.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* partition([Ok(1), Error("a"), Error("b"), Ok(2)])
|
||||
* // -> #([2, 1], ["b", "a"])
|
||||
* ```
|
||||
*/
|
||||
export function partition(results) {
|
||||
return partition_loop(results, toList([]), toList([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the value within a result
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* replace(Ok(1), Nil)
|
||||
* // -> Ok(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* replace(Error(1), Nil)
|
||||
* // -> Error(1)
|
||||
* ```
|
||||
*/
|
||||
export function replace(result, value) {
|
||||
if (result instanceof Ok) {
|
||||
return new Ok(value);
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the error within a result
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* replace_error(Error(1), Nil)
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* replace_error(Ok(1), Nil)
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*/
|
||||
export function replace_error(result, error) {
|
||||
if (result instanceof Ok) {
|
||||
return result;
|
||||
} else {
|
||||
return new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of results, returns only the values inside `Ok`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* values([Ok(1), Error("a"), Ok(3)])
|
||||
* // -> [1, 3]
|
||||
* ```
|
||||
*/
|
||||
export function values(results) {
|
||||
return $list.filter_map(results, (result) => { return result; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a value held within the `Error` of a result by calling a given function
|
||||
* on it, where the given function also returns a result. The two results are
|
||||
* then merged together into one result.
|
||||
*
|
||||
* If the result is an `Ok` rather than `Error` the function is not called and the
|
||||
* result stays the same.
|
||||
*
|
||||
* This function is useful for chaining together computations that may fail
|
||||
* and trying to recover from possible errors.
|
||||
*
|
||||
* If you do not need access to the initial error value, use `result.lazy_or`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* Ok(1) |> try_recover(with: fn(_) { Error("failed to recover") })
|
||||
* // -> Ok(1)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* Error(1) |> try_recover(with: fn(error) { Ok(error + 1) })
|
||||
* // -> Ok(2)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* Error(1) |> try_recover(with: fn(error) { Error("failed to recover") })
|
||||
* // -> Error("failed to recover")
|
||||
* ```
|
||||
*/
|
||||
export function try_recover(result, fun) {
|
||||
if (result instanceof Ok) {
|
||||
return result;
|
||||
} else {
|
||||
let error = result[0];
|
||||
return fun(error);
|
||||
}
|
||||
}
|
||||
412
build/dev/javascript/gleam_stdlib/gleam/set.mjs
Normal file
412
build/dev/javascript/gleam_stdlib/gleam/set.mjs
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
import { CustomType as $CustomType, isEqual } from "../gleam.mjs";
|
||||
import * as $dict from "../gleam/dict.mjs";
|
||||
import * as $list from "../gleam/list.mjs";
|
||||
import * as $result from "../gleam/result.mjs";
|
||||
|
||||
class Set extends $CustomType {
|
||||
constructor(dict) {
|
||||
super();
|
||||
this.dict = dict;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new empty set.
|
||||
*/
|
||||
export function new$() {
|
||||
return new Set($dict.new$());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of members in a set.
|
||||
*
|
||||
* This function runs in constant time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new()
|
||||
* |> insert(1)
|
||||
* |> insert(2)
|
||||
* |> size
|
||||
* // -> 2
|
||||
* ```
|
||||
*/
|
||||
export function size(set) {
|
||||
return $dict.size(set.dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the set is empty.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> is_empty
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert(1) |> is_empty
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_empty(set) {
|
||||
return isEqual(set, new$());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a set contains a given member.
|
||||
*
|
||||
* This function runs in logarithmic time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new()
|
||||
* |> insert(2)
|
||||
* |> contains(2)
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* new()
|
||||
* |> insert(2)
|
||||
* |> contains(1)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function contains(set, member) {
|
||||
let _pipe = set.dict;
|
||||
let _pipe$1 = $dict.get(_pipe, member);
|
||||
return $result.is_ok(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a member from a set. If the set does not contain the member then
|
||||
* the set is returned unchanged.
|
||||
*
|
||||
* This function runs in logarithmic time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new()
|
||||
* |> insert(2)
|
||||
* |> delete(2)
|
||||
* |> contains(1)
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function delete$(set, member) {
|
||||
return new Set($dict.delete$(set.dict, member));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the set into a list of the contained members.
|
||||
*
|
||||
* The list has no specific ordering, any unintentional ordering may change in
|
||||
* future versions of Gleam or Erlang.
|
||||
*
|
||||
* This function runs in linear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new() |> insert(2) |> to_list
|
||||
* // -> [2]
|
||||
* ```
|
||||
*/
|
||||
export function to_list(set) {
|
||||
return $dict.keys(set.dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines all entries into a single value by calling a given function on each
|
||||
* one.
|
||||
*
|
||||
* Sets are not ordered so the values are not returned in any specific order.
|
||||
* Do not write code that relies on the order entries are used by this
|
||||
* function as it may change in later versions of Gleam or Erlang.
|
||||
*
|
||||
* # Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([1, 3, 9])
|
||||
* |> fold(0, fn(accumulator, member) { accumulator + member })
|
||||
* // -> 13
|
||||
* ```
|
||||
*/
|
||||
export function fold(set, initial, reducer) {
|
||||
return $dict.fold(set.dict, initial, (a, k, _) => { return reducer(a, k); });
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set from an existing set, minus any members that a given
|
||||
* function returns `False` for.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
*
|
||||
* from_list([1, 4, 6, 3, 675, 44, 67])
|
||||
* |> filter(keeping: int.is_even)
|
||||
* |> to_list
|
||||
* // -> [4, 6, 44]
|
||||
* ```
|
||||
*/
|
||||
export function filter(set, predicate) {
|
||||
return new Set($dict.filter(set.dict, (m, _) => { return predicate(m); }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set from a given set with all the same entries except any
|
||||
* entry found on the given list.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([1, 2, 3, 4])
|
||||
* |> drop([1, 3])
|
||||
* |> to_list
|
||||
* // -> [2, 4]
|
||||
* ```
|
||||
*/
|
||||
export function drop(set, disallowed) {
|
||||
return $list.fold(disallowed, set, delete$);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set from a given set, only including any members which are in
|
||||
* a given list.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([1, 2, 3])
|
||||
* |> take([1, 3, 5])
|
||||
* |> to_list
|
||||
* // -> [1, 3]
|
||||
* ```
|
||||
*/
|
||||
export function take(set, desired) {
|
||||
return new Set($dict.take(set.dict, desired));
|
||||
}
|
||||
|
||||
function order(first, second) {
|
||||
let $ = $dict.size(first.dict) > $dict.size(second.dict);
|
||||
if ($) {
|
||||
return [first, second];
|
||||
} else {
|
||||
return [second, first];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set that contains members that are present in both given sets.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* intersection(from_list([1, 2]), from_list([2, 3])) |> to_list
|
||||
* // -> [2]
|
||||
* ```
|
||||
*/
|
||||
export function intersection(first, second) {
|
||||
let $ = order(first, second);
|
||||
let larger;
|
||||
let smaller;
|
||||
larger = $[0];
|
||||
smaller = $[1];
|
||||
return take(larger, to_list(smaller));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set that contains members that are present in the first set
|
||||
* but not the second.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list
|
||||
* // -> [1]
|
||||
* ```
|
||||
*/
|
||||
export function difference(first, second) {
|
||||
return drop(first, to_list(second));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a set is fully contained by another.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_subset(from_list([1]), from_list([1, 2]))
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_subset(from_list([1, 2, 3]), from_list([3, 4, 5]))
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_subset(first, second) {
|
||||
return isEqual(intersection(first, second), first);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if two sets contain no common members
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6]))
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5]))
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_disjoint(first, second) {
|
||||
return isEqual(intersection(first, second), new$());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function for each member in a set, discarding the return
|
||||
* value.
|
||||
*
|
||||
* Useful for producing a side effect for every item of a set.
|
||||
*
|
||||
* ```gleam
|
||||
* let set = from_list(["apple", "banana", "cherry"])
|
||||
*
|
||||
* each(set, io.println)
|
||||
* // -> Nil
|
||||
* // apple
|
||||
* // banana
|
||||
* // cherry
|
||||
* ```
|
||||
*
|
||||
* The order of elements in the iteration is an implementation detail that
|
||||
* should not be relied upon.
|
||||
*/
|
||||
export function each(set, fun) {
|
||||
return fold(
|
||||
set,
|
||||
undefined,
|
||||
(nil, member) => {
|
||||
fun(member);
|
||||
return nil;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const token = undefined;
|
||||
|
||||
/**
|
||||
* Inserts an member into the set.
|
||||
*
|
||||
* This function runs in logarithmic time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* new()
|
||||
* |> insert(1)
|
||||
* |> insert(2)
|
||||
* |> size
|
||||
* // -> 2
|
||||
* ```
|
||||
*/
|
||||
export function insert(set, member) {
|
||||
return new Set($dict.insert(set.dict, member, token));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set of the members in a given list.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* import gleam/int
|
||||
* import gleam/list
|
||||
*
|
||||
* [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare)
|
||||
* // -> [1, 2, 3, 4]
|
||||
* ```
|
||||
*/
|
||||
export function from_list(members) {
|
||||
let dict = $list.fold(
|
||||
members,
|
||||
$dict.new$(),
|
||||
(m, k) => { return $dict.insert(m, k, token); },
|
||||
);
|
||||
return new Set(dict);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set from a given set with the result of applying the given
|
||||
* function to each member.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_list([1, 2, 3, 4])
|
||||
* |> map(with: fn(x) { x * 2 })
|
||||
* |> to_list
|
||||
* // -> [2, 4, 6, 8]
|
||||
* ```
|
||||
*/
|
||||
export function map(set, fun) {
|
||||
return fold(
|
||||
set,
|
||||
new$(),
|
||||
(acc, member) => { return insert(acc, fun(member)); },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set that contains all members of both given sets.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* union(from_list([1, 2]), from_list([2, 3])) |> to_list
|
||||
* // -> [1, 2, 3]
|
||||
* ```
|
||||
*/
|
||||
export function union(first, second) {
|
||||
let $ = order(first, second);
|
||||
let larger;
|
||||
let smaller;
|
||||
larger = $[0];
|
||||
smaller = $[1];
|
||||
return fold(smaller, larger, insert);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new set that contains members that are present in either set, but
|
||||
* not both.
|
||||
*
|
||||
* ```gleam
|
||||
* symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list
|
||||
* // -> [1, 2, 4]
|
||||
* ```
|
||||
*/
|
||||
export function symmetric_difference(first, second) {
|
||||
return difference(union(first, second), intersection(first, second));
|
||||
}
|
||||
723
build/dev/javascript/gleam_stdlib/gleam/string.mjs
Normal file
723
build/dev/javascript/gleam_stdlib/gleam/string.mjs
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
import {
|
||||
Ok,
|
||||
Error,
|
||||
Empty as $Empty,
|
||||
prepend as listPrepend,
|
||||
CustomType as $CustomType,
|
||||
remainderInt,
|
||||
divideInt,
|
||||
} from "../gleam.mjs";
|
||||
import * as $list from "../gleam/list.mjs";
|
||||
import * as $option from "../gleam/option.mjs";
|
||||
import { None, Some } from "../gleam/option.mjs";
|
||||
import * as $order from "../gleam/order.mjs";
|
||||
import * as $string_tree from "../gleam/string_tree.mjs";
|
||||
import {
|
||||
string_length as length,
|
||||
lowercase,
|
||||
uppercase,
|
||||
less_than,
|
||||
string_grapheme_slice as grapheme_slice,
|
||||
string_byte_slice as unsafe_byte_slice,
|
||||
crop_string as crop,
|
||||
contains_string as contains,
|
||||
starts_with,
|
||||
ends_with,
|
||||
split_once,
|
||||
trim_start,
|
||||
trim_end,
|
||||
pop_grapheme,
|
||||
graphemes as to_graphemes,
|
||||
codepoint as unsafe_int_to_utf_codepoint,
|
||||
string_to_codepoint_integer_list,
|
||||
utf_codepoint_list_to_string as from_utf_codepoints,
|
||||
utf_codepoint_to_int,
|
||||
inspect as do_inspect,
|
||||
byte_size,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export {
|
||||
byte_size,
|
||||
contains,
|
||||
crop,
|
||||
ends_with,
|
||||
from_utf_codepoints,
|
||||
length,
|
||||
lowercase,
|
||||
pop_grapheme,
|
||||
split_once,
|
||||
starts_with,
|
||||
to_graphemes,
|
||||
trim_end,
|
||||
trim_start,
|
||||
uppercase,
|
||||
utf_codepoint_to_int,
|
||||
};
|
||||
|
||||
class Leading extends $CustomType {}
|
||||
|
||||
class Trailing extends $CustomType {}
|
||||
|
||||
/**
|
||||
* Determines if a `String` is empty.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* is_empty("")
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_empty("the world")
|
||||
* // -> False
|
||||
* ```
|
||||
*/
|
||||
export function is_empty(str) {
|
||||
return str === "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses a `String`.
|
||||
*
|
||||
* This function has to iterate across the whole `String` so it runs in linear
|
||||
* time. Avoid using this in a loop.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* reverse("stressed")
|
||||
* // -> "desserts"
|
||||
* ```
|
||||
*/
|
||||
export function reverse(string) {
|
||||
let _pipe = string;
|
||||
let _pipe$1 = $string_tree.from_string(_pipe);
|
||||
let _pipe$2 = $string_tree.reverse(_pipe$1);
|
||||
return $string_tree.to_string(_pipe$2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `String` by replacing all occurrences of a given substring.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* replace("www.example.com", each: ".", with: "-")
|
||||
* // -> "www-example-com"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* replace("a,b,c,d,e", each: ",", with: "/")
|
||||
* // -> "a/b/c/d/e"
|
||||
* ```
|
||||
*/
|
||||
export function replace(string, pattern, substitute) {
|
||||
let _pipe = string;
|
||||
let _pipe$1 = $string_tree.from_string(_pipe);
|
||||
let _pipe$2 = $string_tree.replace(_pipe$1, pattern, substitute);
|
||||
return $string_tree.to_string(_pipe$2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two `String`s to see which is "larger" by comparing their graphemes.
|
||||
*
|
||||
* This does not compare the size or length of the given `String`s.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* compare("Anthony", "Anthony")
|
||||
* // -> order.Eq
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* compare("A", "B")
|
||||
* // -> order.Lt
|
||||
* ```
|
||||
*/
|
||||
export function compare(a, b) {
|
||||
let $ = a === b;
|
||||
if ($) {
|
||||
return new $order.Eq();
|
||||
} else {
|
||||
let $1 = less_than(a, b);
|
||||
if ($1) {
|
||||
return new $order.Lt();
|
||||
} else {
|
||||
return new $order.Gt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a substring given a start grapheme index and a length. Negative indexes
|
||||
* are taken starting from the *end* of the list.
|
||||
*
|
||||
* This function runs in linear time with the size of the index and the
|
||||
* length. Negative indexes are linear with the size of the input string in
|
||||
* addition to the other costs.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* slice(from: "gleam", at_index: 1, length: 2)
|
||||
* // -> "le"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* slice(from: "gleam", at_index: 1, length: 10)
|
||||
* // -> "leam"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* slice(from: "gleam", at_index: 10, length: 3)
|
||||
* // -> ""
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* slice(from: "gleam", at_index: -2, length: 2)
|
||||
* // -> "am"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* slice(from: "gleam", at_index: -12, length: 2)
|
||||
* // -> ""
|
||||
* ```
|
||||
*/
|
||||
export function slice(string, idx, len) {
|
||||
let $ = len <= 0;
|
||||
if ($) {
|
||||
return "";
|
||||
} else {
|
||||
let $1 = idx < 0;
|
||||
if ($1) {
|
||||
let translated_idx = length(string) + idx;
|
||||
let $2 = translated_idx < 0;
|
||||
if ($2) {
|
||||
return "";
|
||||
} else {
|
||||
return grapheme_slice(string, translated_idx, len);
|
||||
}
|
||||
} else {
|
||||
return grapheme_slice(string, idx, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops *n* graphemes from the end of a `String`.
|
||||
*
|
||||
* This function traverses the full string, so it runs in linear time with the
|
||||
* size of the string. Avoid using this in a loop.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* drop_end(from: "Cigarette Smoking Man", up_to: 2)
|
||||
* // -> "Cigarette Smoking M"
|
||||
* ```
|
||||
*/
|
||||
export function drop_end(string, num_graphemes) {
|
||||
let $ = num_graphemes <= 0;
|
||||
if ($) {
|
||||
return string;
|
||||
} else {
|
||||
return slice(string, 0, length(string) - num_graphemes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `String` by joining two `String`s together.
|
||||
*
|
||||
* This function typically copies both `String`s and runs in linear time, but
|
||||
* the exact behaviour will depend on how the runtime you are using optimises
|
||||
* your code. Benchmark and profile your code if you need to understand its
|
||||
* performance better.
|
||||
*
|
||||
* If you are joining together large string and want to avoid copying any data
|
||||
* you may want to investigate using the [`string_tree`](../gleam/string_tree.html)
|
||||
* module.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* append(to: "butter", suffix: "fly")
|
||||
* // -> "butterfly"
|
||||
* ```
|
||||
*/
|
||||
export function append(first, second) {
|
||||
return first + second;
|
||||
}
|
||||
|
||||
function concat_loop(loop$strings, loop$accumulator) {
|
||||
while (true) {
|
||||
let strings = loop$strings;
|
||||
let accumulator = loop$accumulator;
|
||||
if (strings instanceof $Empty) {
|
||||
return accumulator;
|
||||
} else {
|
||||
let string = strings.head;
|
||||
let strings$1 = strings.tail;
|
||||
loop$strings = strings$1;
|
||||
loop$accumulator = accumulator + string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `String` by joining many `String`s together.
|
||||
*
|
||||
* This function copies all the `String`s and runs in linear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* concat(["never", "the", "less"])
|
||||
* // -> "nevertheless"
|
||||
* ```
|
||||
*/
|
||||
export function concat(strings) {
|
||||
return concat_loop(strings, "");
|
||||
}
|
||||
|
||||
function repeat_loop(loop$times, loop$doubling_acc, loop$acc) {
|
||||
while (true) {
|
||||
let times = loop$times;
|
||||
let doubling_acc = loop$doubling_acc;
|
||||
let acc = loop$acc;
|
||||
let _block;
|
||||
let $ = times % 2;
|
||||
if ($ === 0) {
|
||||
_block = acc;
|
||||
} else {
|
||||
_block = acc + doubling_acc;
|
||||
}
|
||||
let acc$1 = _block;
|
||||
let times$1 = globalThis.Math.trunc(times / 2);
|
||||
let $1 = times$1 <= 0;
|
||||
if ($1) {
|
||||
return acc$1;
|
||||
} else {
|
||||
loop$times = times$1;
|
||||
loop$doubling_acc = doubling_acc + doubling_acc;
|
||||
loop$acc = acc$1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `String` by repeating a `String` a given number of times.
|
||||
*
|
||||
* This function runs in loglinear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* repeat("ha", times: 3)
|
||||
* // -> "hahaha"
|
||||
* ```
|
||||
*/
|
||||
export function repeat(string, times) {
|
||||
let $ = times <= 0;
|
||||
if ($) {
|
||||
return "";
|
||||
} else {
|
||||
return repeat_loop(times, string, "");
|
||||
}
|
||||
}
|
||||
|
||||
function join_loop(loop$strings, loop$separator, loop$accumulator) {
|
||||
while (true) {
|
||||
let strings = loop$strings;
|
||||
let separator = loop$separator;
|
||||
let accumulator = loop$accumulator;
|
||||
if (strings instanceof $Empty) {
|
||||
return accumulator;
|
||||
} else {
|
||||
let string = strings.head;
|
||||
let strings$1 = strings.tail;
|
||||
loop$strings = strings$1;
|
||||
loop$separator = separator;
|
||||
loop$accumulator = (accumulator + separator) + string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins many `String`s together with a given separator.
|
||||
*
|
||||
* This function runs in linear time.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* join(["home","evan","Desktop"], with: "/")
|
||||
* // -> "home/evan/Desktop"
|
||||
* ```
|
||||
*/
|
||||
export function join(strings, separator) {
|
||||
if (strings instanceof $Empty) {
|
||||
return "";
|
||||
} else {
|
||||
let first$1 = strings.head;
|
||||
let rest = strings.tail;
|
||||
return join_loop(rest, separator, first$1);
|
||||
}
|
||||
}
|
||||
|
||||
function padding(size, pad_string) {
|
||||
let pad_string_length = length(pad_string);
|
||||
let num_pads = divideInt(size, pad_string_length);
|
||||
let extra = remainderInt(size, pad_string_length);
|
||||
return repeat(pad_string, num_pads) + slice(pad_string, 0, extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads the start of a `String` until it has a given length.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* pad_start("121", to: 5, with: ".")
|
||||
* // -> "..121"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* pad_start("121", to: 3, with: ".")
|
||||
* // -> "121"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* pad_start("121", to: 2, with: ".")
|
||||
* // -> "121"
|
||||
* ```
|
||||
*/
|
||||
export function pad_start(string, desired_length, pad_string) {
|
||||
let current_length = length(string);
|
||||
let to_pad_length = desired_length - current_length;
|
||||
let $ = to_pad_length <= 0;
|
||||
if ($) {
|
||||
return string;
|
||||
} else {
|
||||
return padding(to_pad_length, pad_string) + string;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads the end of a `String` until it has a given length.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* pad_end("123", to: 5, with: ".")
|
||||
* // -> "123.."
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* pad_end("123", to: 3, with: ".")
|
||||
* // -> "123"
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* pad_end("123", to: 2, with: ".")
|
||||
* // -> "123"
|
||||
* ```
|
||||
*/
|
||||
export function pad_end(string, desired_length, pad_string) {
|
||||
let current_length = length(string);
|
||||
let to_pad_length = desired_length - current_length;
|
||||
let $ = to_pad_length <= 0;
|
||||
if ($) {
|
||||
return string;
|
||||
} else {
|
||||
return string + padding(to_pad_length, pad_string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes whitespace on both sides of a `String`.
|
||||
*
|
||||
* Whitespace in this function is the set of nonbreakable whitespace
|
||||
* codepoints, defined as Pattern_White_Space in [Unicode Standard Annex #31][1].
|
||||
*
|
||||
* [1]: https://unicode.org/reports/tr31/
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* trim(" hats \n")
|
||||
* // -> "hats"
|
||||
* ```
|
||||
*/
|
||||
export function trim(string) {
|
||||
let _pipe = string;
|
||||
let _pipe$1 = trim_start(_pipe);
|
||||
return trim_end(_pipe$1);
|
||||
}
|
||||
|
||||
function to_graphemes_loop(loop$string, loop$acc) {
|
||||
while (true) {
|
||||
let string = loop$string;
|
||||
let acc = loop$acc;
|
||||
let $ = pop_grapheme(string);
|
||||
if ($ instanceof Ok) {
|
||||
let grapheme = $[0][0];
|
||||
let rest = $[0][1];
|
||||
loop$string = rest;
|
||||
loop$acc = listPrepend(grapheme, acc);
|
||||
} else {
|
||||
return acc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of `String`s by splitting a given string on a given substring.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* split("home/gleam/desktop/", on: "/")
|
||||
* // -> ["home", "gleam", "desktop", ""]
|
||||
* ```
|
||||
*/
|
||||
export function split(x, substring) {
|
||||
if (substring === "") {
|
||||
return to_graphemes(x);
|
||||
} else {
|
||||
let _pipe = x;
|
||||
let _pipe$1 = $string_tree.from_string(_pipe);
|
||||
let _pipe$2 = $string_tree.split(_pipe$1, substring);
|
||||
return $list.map(_pipe$2, $string_tree.to_string);
|
||||
}
|
||||
}
|
||||
|
||||
function do_to_utf_codepoints(string) {
|
||||
let _pipe = string;
|
||||
let _pipe$1 = string_to_codepoint_integer_list(_pipe);
|
||||
return $list.map(_pipe$1, unsafe_int_to_utf_codepoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `String` to a `List` of `UtfCodepoint`.
|
||||
*
|
||||
* See <https://en.wikipedia.org/wiki/Code_point> and
|
||||
* <https://en.wikipedia.org/wiki/Unicode#Codespace_and_Code_Points> for an
|
||||
* explanation on code points.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* "a" |> to_utf_codepoints
|
||||
* // -> [UtfCodepoint(97)]
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* // Semantically the same as:
|
||||
* // ["🏳", "️", "", "🌈"] or:
|
||||
* // [waving_white_flag, variant_selector_16, zero_width_joiner, rainbow]
|
||||
* "🏳️🌈" |> to_utf_codepoints
|
||||
* // -> [
|
||||
* // UtfCodepoint(127987),
|
||||
* // UtfCodepoint(65039),
|
||||
* // UtfCodepoint(8205),
|
||||
* // UtfCodepoint(127752),
|
||||
* // ]
|
||||
* ```
|
||||
*/
|
||||
export function to_utf_codepoints(string) {
|
||||
return do_to_utf_codepoints(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an integer to a `UtfCodepoint`.
|
||||
*
|
||||
* Returns an `Error` if the integer does not represent a valid UTF codepoint.
|
||||
*/
|
||||
export function utf_codepoint(value) {
|
||||
let i = value;
|
||||
if (i > 1_114_111) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let i$1 = value;
|
||||
if ((i$1 >= 55_296) && (i$1 <= 57_343)) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let i$2 = value;
|
||||
if (i$2 < 0) {
|
||||
return new Error(undefined);
|
||||
} else {
|
||||
let i$3 = value;
|
||||
return new Ok(unsafe_int_to_utf_codepoint(i$3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `String` into `Option(String)` where an empty `String` becomes
|
||||
* `None`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* to_option("")
|
||||
* // -> None
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* to_option("hats")
|
||||
* // -> Some("hats")
|
||||
* ```
|
||||
*/
|
||||
export function to_option(string) {
|
||||
if (string === "") {
|
||||
return new None();
|
||||
} else {
|
||||
return new Some(string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first grapheme cluster in a given `String` and wraps it in a
|
||||
* `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.
|
||||
* Otherwise, it returns `Ok(String)`.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* first("")
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* first("icecream")
|
||||
* // -> Ok("i")
|
||||
* ```
|
||||
*/
|
||||
export function first(string) {
|
||||
let $ = pop_grapheme(string);
|
||||
if ($ instanceof Ok) {
|
||||
let first$1 = $[0][0];
|
||||
return new Ok(first$1);
|
||||
} else {
|
||||
return $;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last grapheme cluster in a given `String` and wraps it in a
|
||||
* `Result(String, Nil)`. If the `String` is empty, it returns `Error(Nil)`.
|
||||
* Otherwise, it returns `Ok(String)`.
|
||||
*
|
||||
* This function traverses the full string, so it runs in linear time with the
|
||||
* length of the string. Avoid using this in a loop.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* last("")
|
||||
* // -> Error(Nil)
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* last("icecream")
|
||||
* // -> Ok("m")
|
||||
* ```
|
||||
*/
|
||||
export function last(string) {
|
||||
let $ = pop_grapheme(string);
|
||||
if ($ instanceof Ok) {
|
||||
let $1 = $[0][1];
|
||||
if ($1 === "") {
|
||||
let first$1 = $[0][0];
|
||||
return new Ok(first$1);
|
||||
} else {
|
||||
let rest = $1;
|
||||
return new Ok(slice(rest, -1, 1));
|
||||
}
|
||||
} else {
|
||||
return $;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `String` with the first grapheme in the input `String`
|
||||
* converted to uppercase and the remaining graphemes to lowercase.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* capitalise("mamouna")
|
||||
* // -> "Mamouna"
|
||||
* ```
|
||||
*/
|
||||
export function capitalise(string) {
|
||||
let $ = pop_grapheme(string);
|
||||
if ($ instanceof Ok) {
|
||||
let first$1 = $[0][0];
|
||||
let rest = $[0][1];
|
||||
return append(uppercase(first$1), lowercase(rest));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a `String` representation of a term in Gleam syntax.
|
||||
*
|
||||
* This may be occasionally useful for quick-and-dirty printing of values in
|
||||
* scripts. For error reporting and other uses prefer constructing strings by
|
||||
* pattern matching on the values.
|
||||
*
|
||||
* ## Limitations
|
||||
*
|
||||
* The output format of this function is not stable and could change at any
|
||||
* time. The output is not suitable for parsing.
|
||||
*
|
||||
* This function works using runtime reflection, so the output may not be
|
||||
* perfectly accurate for data structures where the runtime structure doesn't
|
||||
* hold enough information to determine the original syntax. For example,
|
||||
* tuples with an Erlang atom in the first position will be mistaken for Gleam
|
||||
* records.
|
||||
*
|
||||
* ## Security and safety
|
||||
*
|
||||
* There is no limit to how large the strings that this function can produce.
|
||||
* Be careful not to call this function with large data structures or you
|
||||
* could use very large amounts of memory, potentially causing runtime
|
||||
* problems.
|
||||
*/
|
||||
export function inspect(term) {
|
||||
let _pipe = term;
|
||||
let _pipe$1 = do_inspect(_pipe);
|
||||
return $string_tree.to_string(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops *n* graphemes from the start of a `String`.
|
||||
*
|
||||
* This function runs in linear time with the number of graphemes to drop.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* drop_start(from: "The Lone Gunmen", up_to: 2)
|
||||
* // -> "e Lone Gunmen"
|
||||
* ```
|
||||
*/
|
||||
export function drop_start(string, num_graphemes) {
|
||||
let $ = num_graphemes <= 0;
|
||||
if ($) {
|
||||
return string;
|
||||
} else {
|
||||
let prefix = grapheme_slice(string, 0, num_graphemes);
|
||||
let prefix_size = byte_size(prefix);
|
||||
return unsafe_byte_slice(
|
||||
string,
|
||||
prefix_size,
|
||||
byte_size(string) - prefix_size,
|
||||
);
|
||||
}
|
||||
}
|
||||
133
build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs
Normal file
133
build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import { toList, CustomType as $CustomType, isEqual } from "../gleam.mjs";
|
||||
import * as $list from "../gleam/list.mjs";
|
||||
import {
|
||||
add as append_tree,
|
||||
concat as from_strings,
|
||||
concat,
|
||||
identity as from_string,
|
||||
identity as to_string,
|
||||
length as byte_size,
|
||||
lowercase,
|
||||
uppercase,
|
||||
graphemes as do_to_graphemes,
|
||||
split,
|
||||
string_replace as replace,
|
||||
} from "../gleam_stdlib.mjs";
|
||||
|
||||
export {
|
||||
append_tree,
|
||||
byte_size,
|
||||
concat,
|
||||
from_string,
|
||||
from_strings,
|
||||
lowercase,
|
||||
replace,
|
||||
split,
|
||||
to_string,
|
||||
uppercase,
|
||||
};
|
||||
|
||||
class All extends $CustomType {}
|
||||
|
||||
/**
|
||||
* Prepends some `StringTree` onto the start of another.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function prepend_tree(tree, prefix) {
|
||||
return append_tree(prefix, tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an empty `StringTree`. Useful as the start of a pipe chaining many
|
||||
* trees together.
|
||||
*/
|
||||
export function new$() {
|
||||
return from_strings(toList([]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends a `String` onto the start of some `StringTree`.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function prepend(tree, prefix) {
|
||||
return append_tree(from_string(prefix), tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a `String` onto the end of some `StringTree`.
|
||||
*
|
||||
* Runs in constant time.
|
||||
*/
|
||||
export function append(tree, second) {
|
||||
return append_tree(tree, from_string(second));
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins the given trees into a new tree separated with the given string.
|
||||
*/
|
||||
export function join(trees, sep) {
|
||||
let _pipe = trees;
|
||||
let _pipe$1 = $list.intersperse(_pipe, from_string(sep));
|
||||
return concat(_pipe$1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a `StringTree` to a new one with the contents reversed.
|
||||
*/
|
||||
export function reverse(tree) {
|
||||
let _pipe = tree;
|
||||
let _pipe$1 = to_string(_pipe);
|
||||
let _pipe$2 = do_to_graphemes(_pipe$1);
|
||||
let _pipe$3 = $list.reverse(_pipe$2);
|
||||
return from_strings(_pipe$3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two string trees to determine if they have the same textual
|
||||
* content.
|
||||
*
|
||||
* Comparing two string trees using the `==` operator may return `False` even
|
||||
* if they have the same content as they may have been build in different ways,
|
||||
* so using this function is often preferred.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_strings(["a", "b"]) == from_string("ab")
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* is_equal(from_strings(["a", "b"]), from_string("ab"))
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function is_equal(a, b) {
|
||||
return isEqual(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects a `StringTree` to determine if it is equivalent to an empty string.
|
||||
*
|
||||
* ## Examples
|
||||
*
|
||||
* ```gleam
|
||||
* from_string("ok") |> is_empty
|
||||
* // -> False
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_string("") |> is_empty
|
||||
* // -> True
|
||||
* ```
|
||||
*
|
||||
* ```gleam
|
||||
* from_strings([]) |> is_empty
|
||||
* // -> True
|
||||
* ```
|
||||
*/
|
||||
export function is_empty(tree) {
|
||||
return isEqual(from_string(""), tree);
|
||||
}
|
||||
1147
build/dev/javascript/gleam_stdlib/gleam/uri.mjs
Normal file
1147
build/dev/javascript/gleam_stdlib/gleam/uri.mjs
Normal file
File diff suppressed because it is too large
Load diff
347
build/dev/javascript/gleam_stdlib/gleam@bit_array.erl
Normal file
347
build/dev/javascript/gleam_stdlib/gleam@bit_array.erl
Normal file
|
|
@ -0,0 +1,347 @@
|
|||
-module(gleam@bit_array).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/bit_array.gleam").
|
||||
-export([from_string/1, bit_size/1, byte_size/1, pad_to_bytes/1, slice/3, is_utf8/1, to_string/1, concat/1, append/2, base64_encode/2, base64_decode/1, base64_url_encode/2, base64_url_decode/1, base16_encode/1, base16_decode/1, inspect/1, compare/2, starts_with/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(" BitArrays are a sequence of binary data of any length.\n").
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 11).
|
||||
?DOC(" Converts a UTF-8 `String` type into a `BitArray`.\n").
|
||||
-spec from_string(binary()) -> bitstring().
|
||||
from_string(X) ->
|
||||
gleam_stdlib:identity(X).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 17).
|
||||
?DOC(" Returns an integer which is the number of bits in the bit array.\n").
|
||||
-spec bit_size(bitstring()) -> integer().
|
||||
bit_size(X) ->
|
||||
erlang:bit_size(X).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 23).
|
||||
?DOC(" Returns an integer which is the number of bytes in the bit array.\n").
|
||||
-spec byte_size(bitstring()) -> integer().
|
||||
byte_size(X) ->
|
||||
erlang:byte_size(X).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 29).
|
||||
?DOC(" Pads a bit array with zeros so that it is a whole number of bytes.\n").
|
||||
-spec pad_to_bytes(bitstring()) -> bitstring().
|
||||
pad_to_bytes(X) ->
|
||||
gleam_stdlib:bit_array_pad_to_bytes(X).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 54).
|
||||
?DOC(
|
||||
" Extracts a sub-section of a bit array.\n"
|
||||
"\n"
|
||||
" The slice will start at given position and continue up to specified\n"
|
||||
" length.\n"
|
||||
" A negative length can be used to extract bytes at the end of a bit array.\n"
|
||||
"\n"
|
||||
" This function runs in constant time.\n"
|
||||
).
|
||||
-spec slice(bitstring(), integer(), integer()) -> {ok, bitstring()} |
|
||||
{error, nil}.
|
||||
slice(String, Position, Length) ->
|
||||
gleam_stdlib:bit_array_slice(String, Position, Length).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 67).
|
||||
-spec is_utf8_loop(bitstring()) -> boolean().
|
||||
is_utf8_loop(Bits) ->
|
||||
case Bits of
|
||||
<<>> ->
|
||||
true;
|
||||
|
||||
<<_/utf8, Rest/binary>> ->
|
||||
is_utf8_loop(Rest);
|
||||
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 62).
|
||||
?DOC(" Tests to see whether a bit array is valid UTF-8.\n").
|
||||
-spec is_utf8(bitstring()) -> boolean().
|
||||
is_utf8(Bits) ->
|
||||
is_utf8_loop(Bits).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 88).
|
||||
?DOC(
|
||||
" Converts a bit array to a string.\n"
|
||||
"\n"
|
||||
" Returns an error if the bit array is invalid UTF-8 data.\n"
|
||||
).
|
||||
-spec to_string(bitstring()) -> {ok, binary()} | {error, nil}.
|
||||
to_string(Bits) ->
|
||||
case is_utf8(Bits) of
|
||||
true ->
|
||||
{ok, gleam_stdlib:identity(Bits)};
|
||||
|
||||
false ->
|
||||
{error, nil}
|
||||
end.
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 109).
|
||||
?DOC(
|
||||
" Creates a new bit array by joining multiple binaries.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" concat([from_string(\"butter\"), from_string(\"fly\")])\n"
|
||||
" // -> from_string(\"butterfly\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec concat(list(bitstring())) -> bitstring().
|
||||
concat(Bit_arrays) ->
|
||||
gleam_stdlib:bit_array_concat(Bit_arrays).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 40).
|
||||
?DOC(
|
||||
" Creates a new bit array by joining two bit arrays.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" append(to: from_string(\"butter\"), suffix: from_string(\"fly\"))\n"
|
||||
" // -> from_string(\"butterfly\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec append(bitstring(), bitstring()) -> bitstring().
|
||||
append(First, Second) ->
|
||||
gleam_stdlib:bit_array_concat([First, Second]).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 118).
|
||||
?DOC(
|
||||
" Encodes a BitArray into a base 64 encoded string.\n"
|
||||
"\n"
|
||||
" If the bit array does not contain a whole number of bytes then it is padded\n"
|
||||
" with zero bits prior to being encoded.\n"
|
||||
).
|
||||
-spec base64_encode(bitstring(), boolean()) -> binary().
|
||||
base64_encode(Input, Padding) ->
|
||||
gleam_stdlib:base64_encode(Input, Padding).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 122).
|
||||
?DOC(" Decodes a base 64 encoded string into a `BitArray`.\n").
|
||||
-spec base64_decode(binary()) -> {ok, bitstring()} | {error, nil}.
|
||||
base64_decode(Encoded) ->
|
||||
Padded = case erlang:byte_size(gleam_stdlib:identity(Encoded)) rem 4 of
|
||||
0 ->
|
||||
Encoded;
|
||||
|
||||
N ->
|
||||
gleam@string:append(
|
||||
Encoded,
|
||||
gleam@string:repeat(<<"="/utf8>>, 4 - N)
|
||||
)
|
||||
end,
|
||||
gleam_stdlib:base64_decode(Padded).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 140).
|
||||
?DOC(
|
||||
" Encodes a `BitArray` into a base 64 encoded string with URL and filename\n"
|
||||
" safe alphabet.\n"
|
||||
"\n"
|
||||
" If the bit array does not contain a whole number of bytes then it is padded\n"
|
||||
" with zero bits prior to being encoded.\n"
|
||||
).
|
||||
-spec base64_url_encode(bitstring(), boolean()) -> binary().
|
||||
base64_url_encode(Input, Padding) ->
|
||||
_pipe = Input,
|
||||
_pipe@1 = gleam_stdlib:base64_encode(_pipe, Padding),
|
||||
_pipe@2 = gleam@string:replace(_pipe@1, <<"+"/utf8>>, <<"-"/utf8>>),
|
||||
gleam@string:replace(_pipe@2, <<"/"/utf8>>, <<"_"/utf8>>).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 150).
|
||||
?DOC(
|
||||
" Decodes a base 64 encoded string with URL and filename safe alphabet into a\n"
|
||||
" `BitArray`.\n"
|
||||
).
|
||||
-spec base64_url_decode(binary()) -> {ok, bitstring()} | {error, nil}.
|
||||
base64_url_decode(Encoded) ->
|
||||
_pipe = Encoded,
|
||||
_pipe@1 = gleam@string:replace(_pipe, <<"-"/utf8>>, <<"+"/utf8>>),
|
||||
_pipe@2 = gleam@string:replace(_pipe@1, <<"_"/utf8>>, <<"/"/utf8>>),
|
||||
base64_decode(_pipe@2).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 164).
|
||||
?DOC(
|
||||
" Encodes a `BitArray` into a base 16 encoded string.\n"
|
||||
"\n"
|
||||
" If the bit array does not contain a whole number of bytes then it is padded\n"
|
||||
" with zero bits prior to being encoded.\n"
|
||||
).
|
||||
-spec base16_encode(bitstring()) -> binary().
|
||||
base16_encode(Input) ->
|
||||
gleam_stdlib:base16_encode(Input).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 170).
|
||||
?DOC(" Decodes a base 16 encoded string into a `BitArray`.\n").
|
||||
-spec base16_decode(binary()) -> {ok, bitstring()} | {error, nil}.
|
||||
base16_decode(Input) ->
|
||||
gleam_stdlib:base16_decode(Input).
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 191).
|
||||
-spec inspect_loop(bitstring(), binary()) -> binary().
|
||||
inspect_loop(Input, Accumulator) ->
|
||||
case Input of
|
||||
<<>> ->
|
||||
Accumulator;
|
||||
|
||||
<<X:1>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X))/binary>>/binary,
|
||||
":size(1)"/utf8>>;
|
||||
|
||||
<<X@1:2>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@1))/binary>>/binary,
|
||||
":size(2)"/utf8>>;
|
||||
|
||||
<<X@2:3>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@2))/binary>>/binary,
|
||||
":size(3)"/utf8>>;
|
||||
|
||||
<<X@3:4>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@3))/binary>>/binary,
|
||||
":size(4)"/utf8>>;
|
||||
|
||||
<<X@4:5>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@4))/binary>>/binary,
|
||||
":size(5)"/utf8>>;
|
||||
|
||||
<<X@5:6>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@5))/binary>>/binary,
|
||||
":size(6)"/utf8>>;
|
||||
|
||||
<<X@6:7>> ->
|
||||
<<<<Accumulator/binary, (erlang:integer_to_binary(X@6))/binary>>/binary,
|
||||
":size(7)"/utf8>>;
|
||||
|
||||
<<X@7, Rest/bitstring>> ->
|
||||
Suffix = case Rest of
|
||||
<<>> ->
|
||||
<<""/utf8>>;
|
||||
|
||||
_ ->
|
||||
<<", "/utf8>>
|
||||
end,
|
||||
Accumulator@1 = <<<<Accumulator/binary,
|
||||
(erlang:integer_to_binary(X@7))/binary>>/binary,
|
||||
Suffix/binary>>,
|
||||
inspect_loop(Rest, Accumulator@1);
|
||||
|
||||
_ ->
|
||||
Accumulator
|
||||
end.
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 187).
|
||||
?DOC(
|
||||
" Converts a bit array to a string containing the decimal value of each byte.\n"
|
||||
"\n"
|
||||
" Use this over `string.inspect` when you have a bit array you want printed\n"
|
||||
" in the array syntax even if it is valid UTF-8.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" inspect(<<0, 20, 0x20, 255>>)\n"
|
||||
" // -> \"<<0, 20, 32, 255>>\"\n"
|
||||
"\n"
|
||||
" inspect(<<100, 5:3>>)\n"
|
||||
" // -> \"<<100, 5:size(3)>>\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec inspect(bitstring()) -> binary().
|
||||
inspect(Input) ->
|
||||
<<(inspect_loop(Input, <<"<<"/utf8>>))/binary, ">>"/utf8>>.
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 232).
|
||||
?DOC(
|
||||
" Compare two bit arrays as sequences of bytes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(<<1>>, <<2>>)\n"
|
||||
" // -> Lt\n"
|
||||
"\n"
|
||||
" compare(<<\"AB\":utf8>>, <<\"AA\":utf8>>)\n"
|
||||
" // -> Gt\n"
|
||||
"\n"
|
||||
" compare(<<1, 2:size(2)>>, with: <<1, 2:size(2)>>)\n"
|
||||
" // -> Eq\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec compare(bitstring(), bitstring()) -> gleam@order:order().
|
||||
compare(A, B) ->
|
||||
case {A, B} of
|
||||
{<<First_byte, First_rest/bitstring>>,
|
||||
<<Second_byte, Second_rest/bitstring>>} ->
|
||||
case {First_byte, Second_byte} of
|
||||
{F, S} when F > S ->
|
||||
gt;
|
||||
|
||||
{F@1, S@1} when F@1 < S@1 ->
|
||||
lt;
|
||||
|
||||
{_, _} ->
|
||||
compare(First_rest, Second_rest)
|
||||
end;
|
||||
|
||||
{<<>>, <<>>} ->
|
||||
eq;
|
||||
|
||||
{_, <<>>} ->
|
||||
gt;
|
||||
|
||||
{<<>>, _} ->
|
||||
lt;
|
||||
|
||||
{First, Second} ->
|
||||
case {gleam_stdlib:bit_array_to_int_and_size(First),
|
||||
gleam_stdlib:bit_array_to_int_and_size(Second)} of
|
||||
{{A@1, _}, {B@1, _}} when A@1 > B@1 ->
|
||||
gt;
|
||||
|
||||
{{A@2, _}, {B@2, _}} when A@2 < B@2 ->
|
||||
lt;
|
||||
|
||||
{{_, Size_a}, {_, Size_b}} when Size_a > Size_b ->
|
||||
gt;
|
||||
|
||||
{{_, Size_a@1}, {_, Size_b@1}} when Size_a@1 < Size_b@1 ->
|
||||
lt;
|
||||
|
||||
{_, _} ->
|
||||
eq
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/bit_array.gleam", 273).
|
||||
?DOC(
|
||||
" Checks whether the first `BitArray` starts with the second one.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" starts_with(<<1, 2, 3, 4>>, <<1, 2>>)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec starts_with(bitstring(), bitstring()) -> boolean().
|
||||
starts_with(Bits, Prefix) ->
|
||||
Prefix_size = erlang:bit_size(Prefix),
|
||||
case Bits of
|
||||
<<Pref:Prefix_size/bitstring, _/bitstring>> when Pref =:= Prefix ->
|
||||
true;
|
||||
|
||||
_ ->
|
||||
false
|
||||
end.
|
||||
352
build/dev/javascript/gleam_stdlib/gleam@bool.erl
Normal file
352
build/dev/javascript/gleam_stdlib/gleam@bool.erl
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
-module(gleam@bool).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/bool.gleam").
|
||||
-export(['and'/2, 'or'/2, negate/1, nor/2, nand/2, exclusive_or/2, exclusive_nor/2, to_string/1, guard/3, lazy_guard/3]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(
|
||||
" A type with two possible values, `True` and `False`. Used to indicate whether\n"
|
||||
" things are... true or false!\n"
|
||||
"\n"
|
||||
" Often is it clearer and offers more type safety to define a custom type\n"
|
||||
" than to use `Bool`. For example, rather than having a `is_teacher: Bool`\n"
|
||||
" field consider having a `role: SchoolRole` field where `SchoolRole` is a custom\n"
|
||||
" type that can be either `Student` or `Teacher`.\n"
|
||||
).
|
||||
|
||||
-file("src/gleam/bool.gleam", 31).
|
||||
?DOC(
|
||||
" Returns the and of two bools, but it evaluates both arguments.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `&&` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" and(True, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" and(False, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" False |> and(True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec 'and'(boolean(), boolean()) -> boolean().
|
||||
'and'(A, B) ->
|
||||
A andalso B.
|
||||
|
||||
-file("src/gleam/bool.gleam", 57).
|
||||
?DOC(
|
||||
" Returns the or of two bools, but it evaluates both arguments.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `||` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(True, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(False, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" False |> or(True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec 'or'(boolean(), boolean()) -> boolean().
|
||||
'or'(A, B) ->
|
||||
A orelse B.
|
||||
|
||||
-file("src/gleam/bool.gleam", 77).
|
||||
?DOC(
|
||||
" Returns the opposite bool value.\n"
|
||||
"\n"
|
||||
" This is the same as the `!` or `not` operators in some other languages.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec negate(boolean()) -> boolean().
|
||||
negate(Bool) ->
|
||||
not Bool.
|
||||
|
||||
-file("src/gleam/bool.gleam", 105).
|
||||
?DOC(
|
||||
" Returns the nor of two bools.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nor(False, False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nor(False, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nor(True, False)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nor(True, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec nor(boolean(), boolean()) -> boolean().
|
||||
nor(A, B) ->
|
||||
not (A orelse B).
|
||||
|
||||
-file("src/gleam/bool.gleam", 133).
|
||||
?DOC(
|
||||
" Returns the nand of two bools.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nand(False, False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nand(False, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nand(True, False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" nand(True, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec nand(boolean(), boolean()) -> boolean().
|
||||
nand(A, B) ->
|
||||
not (A andalso B).
|
||||
|
||||
-file("src/gleam/bool.gleam", 161).
|
||||
?DOC(
|
||||
" Returns the exclusive or of two bools.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_or(False, False)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_or(False, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_or(True, False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_or(True, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec exclusive_or(boolean(), boolean()) -> boolean().
|
||||
exclusive_or(A, B) ->
|
||||
A /= B.
|
||||
|
||||
-file("src/gleam/bool.gleam", 189).
|
||||
?DOC(
|
||||
" Returns the exclusive nor of two bools.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_nor(False, False)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_nor(False, True)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_nor(True, False)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exclusive_nor(True, True)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec exclusive_nor(boolean(), boolean()) -> boolean().
|
||||
exclusive_nor(A, B) ->
|
||||
A =:= B.
|
||||
|
||||
-file("src/gleam/bool.gleam", 207).
|
||||
?DOC(
|
||||
" Returns a string representation of the given bool.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_string(True)\n"
|
||||
" // -> \"True\"\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_string(False)\n"
|
||||
" // -> \"False\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_string(boolean()) -> binary().
|
||||
to_string(Bool) ->
|
||||
case Bool of
|
||||
false ->
|
||||
<<"False"/utf8>>;
|
||||
|
||||
true ->
|
||||
<<"True"/utf8>>
|
||||
end.
|
||||
|
||||
-file("src/gleam/bool.gleam", 266).
|
||||
?DOC(
|
||||
" Run a callback function if the given bool is `False`, otherwise return a\n"
|
||||
" default value.\n"
|
||||
"\n"
|
||||
" With a `use` expression this function can simulate the early-return pattern\n"
|
||||
" found in some other programming languages.\n"
|
||||
"\n"
|
||||
" In a procedural language:\n"
|
||||
"\n"
|
||||
" ```js\n"
|
||||
" if (predicate) return value;\n"
|
||||
" // ...\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" In Gleam with a `use` expression:\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" use <- guard(when: predicate, return: value)\n"
|
||||
" // ...\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" Like everything in Gleam `use` is an expression, so it short circuits the\n"
|
||||
" current block, not the entire function. As a result you can assign the value\n"
|
||||
" to a variable:\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let x = {\n"
|
||||
" use <- guard(when: predicate, return: value)\n"
|
||||
" // ...\n"
|
||||
" }\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" Note that unlike in procedural languages the `return` value is evaluated\n"
|
||||
" even when the predicate is `False`, so it is advisable not to perform\n"
|
||||
" expensive computation nor side-effects there.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let name = \"\"\n"
|
||||
" use <- guard(when: name == \"\", return: \"Welcome!\")\n"
|
||||
" \"Hello, \" <> name\n"
|
||||
" // -> \"Welcome!\"\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let name = \"Kamaka\"\n"
|
||||
" use <- guard(when: name == \"\", return: \"Welcome!\")\n"
|
||||
" \"Hello, \" <> name\n"
|
||||
" // -> \"Hello, Kamaka\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec guard(boolean(), BSY, fun(() -> BSY)) -> BSY.
|
||||
guard(Requirement, Consequence, Alternative) ->
|
||||
case Requirement of
|
||||
true ->
|
||||
Consequence;
|
||||
|
||||
false ->
|
||||
Alternative()
|
||||
end.
|
||||
|
||||
-file("src/gleam/bool.gleam", 307).
|
||||
?DOC(
|
||||
" Runs a callback function if the given bool is `True`, otherwise runs an\n"
|
||||
" alternative callback function.\n"
|
||||
"\n"
|
||||
" Useful when further computation should be delayed regardless of the given\n"
|
||||
" bool's value.\n"
|
||||
"\n"
|
||||
" See [`guard`](#guard) for more info.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let name = \"Kamaka\"\n"
|
||||
" let inquiry = fn() { \"How may we address you?\" }\n"
|
||||
" use <- lazy_guard(when: name == \"\", return: inquiry)\n"
|
||||
" \"Hello, \" <> name\n"
|
||||
" // -> \"Hello, Kamaka\"\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" let name = \"\"\n"
|
||||
" let greeting = fn() { \"Hello, \" <> name }\n"
|
||||
" use <- lazy_guard(when: name == \"\", otherwise: greeting)\n"
|
||||
" let number = int.random(99)\n"
|
||||
" let name = \"User \" <> int.to_string(number)\n"
|
||||
" \"Welcome, \" <> name\n"
|
||||
" // -> \"Welcome, User 54\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_guard(boolean(), fun(() -> BSZ), fun(() -> BSZ)) -> BSZ.
|
||||
lazy_guard(Requirement, Consequence, Alternative) ->
|
||||
case Requirement of
|
||||
true ->
|
||||
Consequence();
|
||||
|
||||
false ->
|
||||
Alternative()
|
||||
end.
|
||||
211
build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl
Normal file
211
build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
-module(gleam@bytes_tree).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/bytes_tree.gleam").
|
||||
-export([append_tree/2, prepend_tree/2, concat/1, new/0, from_string/1, prepend_string/2, append_string/2, from_string_tree/1, from_bit_array/1, prepend/2, append/2, concat_bit_arrays/1, to_bit_array/1, byte_size/1]).
|
||||
-export_type([bytes_tree/0]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(
|
||||
" `BytesTree` is a type used for efficiently building binary content to be\n"
|
||||
" written to a file or a socket. Internally it is represented as tree so to\n"
|
||||
" append or prepend to a bytes tree is a constant time operation that\n"
|
||||
" allocates a new node in the tree without copying any of the content. When\n"
|
||||
" writing to an output stream the tree is traversed and the content is sent\n"
|
||||
" directly rather than copying it into a single buffer beforehand.\n"
|
||||
"\n"
|
||||
" If we append one bit array to another the bit arrays must be copied to a\n"
|
||||
" new location in memory so that they can sit together. This behaviour\n"
|
||||
" enables efficient reading of the data but copying can be expensive,\n"
|
||||
" especially if we want to join many bit arrays together.\n"
|
||||
"\n"
|
||||
" BytesTree is different in that it can be joined together in constant\n"
|
||||
" time using minimal memory, and then can be efficiently converted to a\n"
|
||||
" bit array using the `to_bit_array` function.\n"
|
||||
"\n"
|
||||
" Byte trees are always byte aligned, so that a number of bits that is not\n"
|
||||
" divisible by 8 will be padded with 0s.\n"
|
||||
"\n"
|
||||
" On Erlang this type is compatible with Erlang's iolists.\n"
|
||||
).
|
||||
|
||||
-opaque bytes_tree() :: {bytes, bitstring()} |
|
||||
{text, gleam@string_tree:string_tree()} |
|
||||
{many, list(bytes_tree())}.
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 68).
|
||||
?DOC(
|
||||
" Appends a bytes tree onto the end of another.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec append_tree(bytes_tree(), bytes_tree()) -> bytes_tree().
|
||||
append_tree(First, Second) ->
|
||||
gleam_stdlib:iodata_append(First, Second).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 59).
|
||||
?DOC(
|
||||
" Prepends a bytes tree onto the start of another.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec prepend_tree(bytes_tree(), bytes_tree()) -> bytes_tree().
|
||||
prepend_tree(Second, First) ->
|
||||
gleam_stdlib:iodata_append(First, Second).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 98).
|
||||
?DOC(
|
||||
" Joins a list of bytes trees into a single one.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec concat(list(bytes_tree())) -> bytes_tree().
|
||||
concat(Trees) ->
|
||||
gleam_stdlib:identity(Trees).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 35).
|
||||
?DOC(
|
||||
" Create an empty `BytesTree`. Useful as the start of a pipe chaining many\n"
|
||||
" trees together.\n"
|
||||
).
|
||||
-spec new() -> bytes_tree().
|
||||
new() ->
|
||||
gleam_stdlib:identity([]).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 118).
|
||||
?DOC(
|
||||
" Creates a new bytes tree from a string.\n"
|
||||
"\n"
|
||||
" Runs in constant time when running on Erlang.\n"
|
||||
" Runs in linear time otherwise.\n"
|
||||
).
|
||||
-spec from_string(binary()) -> bytes_tree().
|
||||
from_string(String) ->
|
||||
gleam_stdlib:wrap_list(String).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 80).
|
||||
?DOC(
|
||||
" Prepends a string onto the start of a bytes tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time when running on Erlang.\n"
|
||||
" Runs in linear time with the length of the string otherwise.\n"
|
||||
).
|
||||
-spec prepend_string(bytes_tree(), binary()) -> bytes_tree().
|
||||
prepend_string(Second, First) ->
|
||||
gleam_stdlib:iodata_append(gleam_stdlib:wrap_list(First), Second).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 89).
|
||||
?DOC(
|
||||
" Appends a string onto the end of a bytes tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time when running on Erlang.\n"
|
||||
" Runs in linear time with the length of the string otherwise.\n"
|
||||
).
|
||||
-spec append_string(bytes_tree(), binary()) -> bytes_tree().
|
||||
append_string(First, Second) ->
|
||||
gleam_stdlib:iodata_append(First, gleam_stdlib:wrap_list(Second)).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 128).
|
||||
?DOC(
|
||||
" Creates a new bytes tree from a string tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time when running on Erlang.\n"
|
||||
" Runs in linear time otherwise.\n"
|
||||
).
|
||||
-spec from_string_tree(gleam@string_tree:string_tree()) -> bytes_tree().
|
||||
from_string_tree(Tree) ->
|
||||
gleam_stdlib:wrap_list(Tree).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 136).
|
||||
?DOC(
|
||||
" Creates a new bytes tree from a bit array.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec from_bit_array(bitstring()) -> bytes_tree().
|
||||
from_bit_array(Bits) ->
|
||||
_pipe = Bits,
|
||||
_pipe@1 = gleam_stdlib:bit_array_pad_to_bytes(_pipe),
|
||||
gleam_stdlib:wrap_list(_pipe@1).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 43).
|
||||
?DOC(
|
||||
" Prepends a bit array to the start of a bytes tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec prepend(bytes_tree(), bitstring()) -> bytes_tree().
|
||||
prepend(Second, First) ->
|
||||
gleam_stdlib:iodata_append(from_bit_array(First), Second).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 51).
|
||||
?DOC(
|
||||
" Appends a bit array to the end of a bytes tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec append(bytes_tree(), bitstring()) -> bytes_tree().
|
||||
append(First, Second) ->
|
||||
gleam_stdlib:iodata_append(First, from_bit_array(Second)).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 106).
|
||||
?DOC(
|
||||
" Joins a list of bit arrays into a single bytes tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec concat_bit_arrays(list(bitstring())) -> bytes_tree().
|
||||
concat_bit_arrays(Bits) ->
|
||||
_pipe = Bits,
|
||||
_pipe@1 = gleam@list:map(_pipe, fun from_bit_array/1),
|
||||
gleam_stdlib:identity(_pipe@1).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 162).
|
||||
-spec to_list(list(list(bytes_tree())), list(bitstring())) -> list(bitstring()).
|
||||
to_list(Stack, Acc) ->
|
||||
case Stack of
|
||||
[] ->
|
||||
Acc;
|
||||
|
||||
[[] | Remaining_stack] ->
|
||||
to_list(Remaining_stack, Acc);
|
||||
|
||||
[[{bytes, Bits} | Rest] | Remaining_stack@1] ->
|
||||
to_list([Rest | Remaining_stack@1], [Bits | Acc]);
|
||||
|
||||
[[{text, Tree} | Rest@1] | Remaining_stack@2] ->
|
||||
Bits@1 = gleam_stdlib:identity(unicode:characters_to_binary(Tree)),
|
||||
to_list([Rest@1 | Remaining_stack@2], [Bits@1 | Acc]);
|
||||
|
||||
[[{many, Trees} | Rest@2] | Remaining_stack@3] ->
|
||||
to_list([Trees, Rest@2 | Remaining_stack@3], Acc)
|
||||
end.
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 155).
|
||||
?DOC(
|
||||
" Turns a bytes tree into a bit array.\n"
|
||||
"\n"
|
||||
" Runs in linear time.\n"
|
||||
"\n"
|
||||
" When running on Erlang this function is implemented natively by the\n"
|
||||
" virtual machine and is highly optimised.\n"
|
||||
).
|
||||
-spec to_bit_array(bytes_tree()) -> bitstring().
|
||||
to_bit_array(Tree) ->
|
||||
erlang:list_to_bitstring(Tree).
|
||||
|
||||
-file("src/gleam/bytes_tree.gleam", 186).
|
||||
?DOC(
|
||||
" Returns the size of the bytes tree's content in bytes.\n"
|
||||
"\n"
|
||||
" Runs in linear time.\n"
|
||||
).
|
||||
-spec byte_size(bytes_tree()) -> integer().
|
||||
byte_size(Tree) ->
|
||||
erlang:iolist_size(Tree).
|
||||
561
build/dev/javascript/gleam_stdlib/gleam@dict.erl
Normal file
561
build/dev/javascript/gleam_stdlib/gleam@dict.erl
Normal file
|
|
@ -0,0 +1,561 @@
|
|||
-module(gleam@dict).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/dict.gleam").
|
||||
-export([size/1, is_empty/1, to_list/1, new/0, get/2, has_key/2, insert/3, from_list/1, keys/1, values/1, take/2, merge/2, delete/2, drop/2, upsert/3, fold/3, map_values/2, filter/2, each/2, combine/3]).
|
||||
-export_type([dict/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-type dict(KG, KH) :: any() | {gleam_phantom, KG, KH}.
|
||||
|
||||
-file("src/gleam/dict.gleam", 36).
|
||||
?DOC(
|
||||
" Determines the number of key-value pairs in the dict.\n"
|
||||
" This function runs in constant time and does not need to iterate the dict.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> size\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"key\", \"value\") |> size\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec size(dict(any(), any())) -> integer().
|
||||
size(Dict) ->
|
||||
maps:size(Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 52).
|
||||
?DOC(
|
||||
" Determines whether or not the dict is empty.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> is_empty\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"b\", 1) |> is_empty\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_empty(dict(any(), any())) -> boolean().
|
||||
is_empty(Dict) ->
|
||||
maps:size(Dict) =:= 0.
|
||||
|
||||
-file("src/gleam/dict.gleam", 80).
|
||||
?DOC(
|
||||
" Converts the dict to a list of 2-element tuples `#(key, value)`, one for\n"
|
||||
" each key-value pair in the dict.\n"
|
||||
"\n"
|
||||
" The tuples in the list have no specific order.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" Calling `to_list` on an empty `dict` returns an empty list.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> to_list\n"
|
||||
" // -> []\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" The ordering of elements in the resulting list is an implementation detail\n"
|
||||
" that should not be relied upon.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"b\", 1) |> insert(\"a\", 0) |> insert(\"c\", 2) |> to_list\n"
|
||||
" // -> [#(\"a\", 0), #(\"b\", 1), #(\"c\", 2)]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_list(dict(KQ, KR)) -> list({KQ, KR}).
|
||||
to_list(Dict) ->
|
||||
maps:to_list(Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 129).
|
||||
?DOC(" Creates a fresh dict that contains no values.\n").
|
||||
-spec new() -> dict(any(), any()).
|
||||
new() ->
|
||||
maps:new().
|
||||
|
||||
-file("src/gleam/dict.gleam", 150).
|
||||
?DOC(
|
||||
" Fetches a value from a dict for a given key.\n"
|
||||
"\n"
|
||||
" The dict may not have a value for the key, so the value is wrapped in a\n"
|
||||
" `Result`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0) |> get(\"a\")\n"
|
||||
" // -> Ok(0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0) |> get(\"b\")\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec get(dict(LT, LU), LT) -> {ok, LU} | {error, nil}.
|
||||
get(From, Get) ->
|
||||
gleam_stdlib:map_get(From, Get).
|
||||
|
||||
-file("src/gleam/dict.gleam", 116).
|
||||
?DOC(
|
||||
" Determines whether or not a value present in the dict for a given key.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0) |> has_key(\"a\")\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0) |> has_key(\"b\")\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec has_key(dict(LH, any()), LH) -> boolean().
|
||||
has_key(Dict, Key) ->
|
||||
maps:is_key(Key, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 169).
|
||||
?DOC(
|
||||
" Inserts a value into the dict with the given key.\n"
|
||||
"\n"
|
||||
" If the dict already has a value for the given key then the value is\n"
|
||||
" replaced with the new value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0)\n"
|
||||
" // -> from_list([#(\"a\", 0)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(\"a\", 0) |> insert(\"a\", 5)\n"
|
||||
" // -> from_list([#(\"a\", 5)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec insert(dict(LZ, MA), LZ, MA) -> dict(LZ, MA).
|
||||
insert(Dict, Key, Value) ->
|
||||
maps:put(Key, Value, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 92).
|
||||
-spec from_list_loop(list({LA, LB}), dict(LA, LB)) -> dict(LA, LB).
|
||||
from_list_loop(List, Initial) ->
|
||||
case List of
|
||||
[] ->
|
||||
Initial;
|
||||
|
||||
[{Key, Value} | Rest] ->
|
||||
from_list_loop(Rest, insert(Initial, Key, Value))
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 88).
|
||||
?DOC(
|
||||
" Converts a list of 2-element tuples `#(key, value)` to a dict.\n"
|
||||
"\n"
|
||||
" If two tuples have the same key the last one in the list will be the one\n"
|
||||
" that is present in the dict.\n"
|
||||
).
|
||||
-spec from_list(list({KV, KW})) -> dict(KV, KW).
|
||||
from_list(List) ->
|
||||
maps:from_list(List).
|
||||
|
||||
-file("src/gleam/dict.gleam", 223).
|
||||
-spec reverse_and_concat(list(NJ), list(NJ)) -> list(NJ).
|
||||
reverse_and_concat(Remaining, Accumulator) ->
|
||||
case Remaining of
|
||||
[] ->
|
||||
Accumulator;
|
||||
|
||||
[First | Rest] ->
|
||||
reverse_and_concat(Rest, [First | Accumulator])
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 216).
|
||||
-spec do_keys_loop(list({NE, any()}), list(NE)) -> list(NE).
|
||||
do_keys_loop(List, Acc) ->
|
||||
case List of
|
||||
[] ->
|
||||
reverse_and_concat(Acc, []);
|
||||
|
||||
[{Key, _} | Rest] ->
|
||||
do_keys_loop(Rest, [Key | Acc])
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 212).
|
||||
?DOC(
|
||||
" Gets a list of all keys in a given dict.\n"
|
||||
"\n"
|
||||
" Dicts are not ordered so the keys are not returned in any specific order. Do\n"
|
||||
" not write code that relies on the order keys are returned by this function\n"
|
||||
" as it may change in later versions of Gleam or Erlang.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> keys\n"
|
||||
" // -> [\"a\", \"b\"]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec keys(dict(MZ, any())) -> list(MZ).
|
||||
keys(Dict) ->
|
||||
maps:keys(Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 249).
|
||||
-spec do_values_loop(list({any(), NT}), list(NT)) -> list(NT).
|
||||
do_values_loop(List, Acc) ->
|
||||
case List of
|
||||
[] ->
|
||||
reverse_and_concat(Acc, []);
|
||||
|
||||
[{_, Value} | Rest] ->
|
||||
do_values_loop(Rest, [Value | Acc])
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 244).
|
||||
?DOC(
|
||||
" Gets a list of all values in a given dict.\n"
|
||||
"\n"
|
||||
" Dicts are not ordered so the values are not returned in any specific order. Do\n"
|
||||
" not write code that relies on the order values are returned by this function\n"
|
||||
" as it may change in later versions of Gleam or Erlang.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> values\n"
|
||||
" // -> [0, 1]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec values(dict(any(), NO)) -> list(NO).
|
||||
values(Dict) ->
|
||||
maps:values(Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 318).
|
||||
-spec do_take_loop(dict(OX, OY), list(OX), dict(OX, OY)) -> dict(OX, OY).
|
||||
do_take_loop(Dict, Desired_keys, Acc) ->
|
||||
Insert = fun(Taken, Key) -> case gleam_stdlib:map_get(Dict, Key) of
|
||||
{ok, Value} ->
|
||||
insert(Taken, Key, Value);
|
||||
|
||||
{error, _} ->
|
||||
Taken
|
||||
end end,
|
||||
case Desired_keys of
|
||||
[] ->
|
||||
Acc;
|
||||
|
||||
[First | Rest] ->
|
||||
do_take_loop(Dict, Rest, Insert(Acc, First))
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 309).
|
||||
?DOC(
|
||||
" Creates a new dict from a given dict, only including any entries for which the\n"
|
||||
" keys are in a given list.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" |> take([\"b\"])\n"
|
||||
" // -> from_list([#(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" |> take([\"a\", \"b\", \"c\"])\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec take(dict(OJ, OK), list(OJ)) -> dict(OJ, OK).
|
||||
take(Dict, Desired_keys) ->
|
||||
maps:with(Desired_keys, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 363).
|
||||
-spec insert_pair(dict(PV, PW), {PV, PW}) -> dict(PV, PW).
|
||||
insert_pair(Dict, Pair) ->
|
||||
insert(Dict, erlang:element(1, Pair), erlang:element(2, Pair)).
|
||||
|
||||
-file("src/gleam/dict.gleam", 356).
|
||||
-spec fold_inserts(list({PO, PP}), dict(PO, PP)) -> dict(PO, PP).
|
||||
fold_inserts(New_entries, Dict) ->
|
||||
case New_entries of
|
||||
[] ->
|
||||
Dict;
|
||||
|
||||
[First | Rest] ->
|
||||
fold_inserts(Rest, insert_pair(Dict, First))
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 350).
|
||||
?DOC(
|
||||
" Creates a new dict from a pair of given dicts by combining their entries.\n"
|
||||
"\n"
|
||||
" If there are entries with the same keys in both dicts the entry from the\n"
|
||||
" second dict takes precedence.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" let b = from_list([#(\"b\", 2), #(\"c\", 3)])\n"
|
||||
" merge(a, b)\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 2), #(\"c\", 3)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec merge(dict(PG, PH), dict(PG, PH)) -> dict(PG, PH).
|
||||
merge(Dict, New_entries) ->
|
||||
maps:merge(Dict, New_entries).
|
||||
|
||||
-file("src/gleam/dict.gleam", 382).
|
||||
?DOC(
|
||||
" Creates a new dict from a given dict with all the same entries except for the\n"
|
||||
" one with a given key, if it exists.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"a\")\n"
|
||||
" // -> from_list([#(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> delete(\"c\")\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec delete(dict(QB, QC), QB) -> dict(QB, QC).
|
||||
delete(Dict, Key) ->
|
||||
maps:remove(Key, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 410).
|
||||
?DOC(
|
||||
" Creates a new dict from a given dict with all the same entries except any with\n"
|
||||
" keys found in a given list.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\"])\n"
|
||||
" // -> from_list([#(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"c\"])\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)]) |> drop([\"a\", \"b\", \"c\"])\n"
|
||||
" // -> from_list([])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec drop(dict(QN, QO), list(QN)) -> dict(QN, QO).
|
||||
drop(Dict, Disallowed_keys) ->
|
||||
case Disallowed_keys of
|
||||
[] ->
|
||||
Dict;
|
||||
|
||||
[First | Rest] ->
|
||||
drop(delete(Dict, First), Rest)
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 440).
|
||||
?DOC(
|
||||
" Creates a new dict with one entry inserted or updated using a given function.\n"
|
||||
"\n"
|
||||
" If there was not an entry in the dict for the given key then the function\n"
|
||||
" gets `None` as its argument, otherwise it gets `Some(value)`.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let dict = from_list([#(\"a\", 0)])\n"
|
||||
" let increment = fn(x) {\n"
|
||||
" case x {\n"
|
||||
" Some(i) -> i + 1\n"
|
||||
" None -> 0\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" upsert(dict, \"a\", increment)\n"
|
||||
" // -> from_list([#(\"a\", 1)])\n"
|
||||
"\n"
|
||||
" upsert(dict, \"b\", increment)\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 0)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec upsert(dict(QU, QV), QU, fun((gleam@option:option(QV)) -> QV)) -> dict(QU, QV).
|
||||
upsert(Dict, Key, Fun) ->
|
||||
case gleam_stdlib:map_get(Dict, Key) of
|
||||
{ok, Value} ->
|
||||
insert(Dict, Key, Fun({some, Value}));
|
||||
|
||||
{error, _} ->
|
||||
insert(Dict, Key, Fun(none))
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 484).
|
||||
-spec fold_loop(list({RG, RH}), RJ, fun((RJ, RG, RH) -> RJ)) -> RJ.
|
||||
fold_loop(List, Initial, Fun) ->
|
||||
case List of
|
||||
[] ->
|
||||
Initial;
|
||||
|
||||
[{K, V} | Rest] ->
|
||||
fold_loop(Rest, Fun(Initial, K, V), Fun)
|
||||
end.
|
||||
|
||||
-file("src/gleam/dict.gleam", 476).
|
||||
?DOC(
|
||||
" Combines all entries into a single value by calling a given function on each\n"
|
||||
" one.\n"
|
||||
"\n"
|
||||
" Dicts are not ordered so the values are not returned in any specific order. Do\n"
|
||||
" not write code that relies on the order entries are used by this function\n"
|
||||
" as it may change in later versions of Gleam or Erlang.\n"
|
||||
"\n"
|
||||
" # Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n"
|
||||
" fold(dict, 0, fn(accumulator, key, value) { accumulator + value })\n"
|
||||
" // -> 13\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/string\n"
|
||||
"\n"
|
||||
" let dict = from_list([#(\"a\", 1), #(\"b\", 3), #(\"c\", 9)])\n"
|
||||
" fold(dict, \"\", fn(accumulator, key, value) {\n"
|
||||
" string.append(accumulator, key)\n"
|
||||
" })\n"
|
||||
" // -> \"abc\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec fold(dict(RB, RC), RF, fun((RF, RB, RC) -> RF)) -> RF.
|
||||
fold(Dict, Initial, Fun) ->
|
||||
fold_loop(maps:to_list(Dict), Initial, Fun).
|
||||
|
||||
-file("src/gleam/dict.gleam", 188).
|
||||
?DOC(
|
||||
" Updates all values in a given dict by calling a given function on each key\n"
|
||||
" and value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(3, 3), #(2, 4)])\n"
|
||||
" |> map_values(fn(key, value) { key * value })\n"
|
||||
" // -> from_list([#(3, 9), #(2, 8)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map_values(dict(ML, MM), fun((ML, MM) -> MP)) -> dict(ML, MP).
|
||||
map_values(Dict, Fun) ->
|
||||
maps:map(Fun, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 273).
|
||||
?DOC(
|
||||
" Creates a new dict from a given dict, minus any entries that a given function\n"
|
||||
" returns `False` for.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" |> filter(fn(key, value) { value != 0 })\n"
|
||||
" // -> from_list([#(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" |> filter(fn(key, value) { True })\n"
|
||||
" // -> from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec filter(dict(NX, NY), fun((NX, NY) -> boolean())) -> dict(NX, NY).
|
||||
filter(Dict, Predicate) ->
|
||||
maps:filter(Predicate, Dict).
|
||||
|
||||
-file("src/gleam/dict.gleam", 517).
|
||||
?DOC(
|
||||
" Calls a function for each key and value in a dict, discarding the return\n"
|
||||
" value.\n"
|
||||
"\n"
|
||||
" Useful for producing a side effect for every item of a dict.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/io\n"
|
||||
"\n"
|
||||
" let dict = from_list([#(\"a\", \"apple\"), #(\"b\", \"banana\"), #(\"c\", \"cherry\")])\n"
|
||||
"\n"
|
||||
" each(dict, fn(k, v) {\n"
|
||||
" io.println(key <> \" => \" <> value)\n"
|
||||
" })\n"
|
||||
" // -> Nil\n"
|
||||
" // a => apple\n"
|
||||
" // b => banana\n"
|
||||
" // c => cherry\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" The order of elements in the iteration is an implementation detail that\n"
|
||||
" should not be relied upon.\n"
|
||||
).
|
||||
-spec each(dict(RK, RL), fun((RK, RL) -> any())) -> nil.
|
||||
each(Dict, Fun) ->
|
||||
fold(
|
||||
Dict,
|
||||
nil,
|
||||
fun(Nil, K, V) ->
|
||||
Fun(K, V),
|
||||
Nil
|
||||
end
|
||||
).
|
||||
|
||||
-file("src/gleam/dict.gleam", 538).
|
||||
?DOC(
|
||||
" Creates a new dict from a pair of given dicts by combining their entries.\n"
|
||||
"\n"
|
||||
" If there are entries with the same keys in both dicts the given function is\n"
|
||||
" used to determine the new value to use in the resulting dict.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let a = from_list([#(\"a\", 0), #(\"b\", 1)])\n"
|
||||
" let b = from_list([#(\"a\", 2), #(\"c\", 3)])\n"
|
||||
" combine(a, b, fn(one, other) { one + other })\n"
|
||||
" // -> from_list([#(\"a\", 2), #(\"b\", 1), #(\"c\", 3)])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec combine(dict(RP, RQ), dict(RP, RQ), fun((RQ, RQ) -> RQ)) -> dict(RP, RQ).
|
||||
combine(Dict, Other, Fun) ->
|
||||
fold(
|
||||
Dict,
|
||||
Other,
|
||||
fun(Acc, Key, Value) -> case gleam_stdlib:map_get(Acc, Key) of
|
||||
{ok, Other_value} ->
|
||||
insert(Acc, Key, Fun(Value, Other_value));
|
||||
|
||||
{error, _} ->
|
||||
insert(Acc, Key, Value)
|
||||
end end
|
||||
).
|
||||
106
build/dev/javascript/gleam_stdlib/gleam@dynamic.erl
Normal file
106
build/dev/javascript/gleam_stdlib/gleam@dynamic.erl
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
-module(gleam@dynamic).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/dynamic.gleam").
|
||||
-export([classify/1, bool/1, string/1, float/1, int/1, bit_array/1, list/1, array/1, properties/1, nil/0]).
|
||||
-export_type([dynamic_/0]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-type dynamic_() :: any().
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 30).
|
||||
?DOC(
|
||||
" Return a string indicating the type of the dynamic value.\n"
|
||||
"\n"
|
||||
" This function may be useful for constructing error messages or logs. If you\n"
|
||||
" want to turn dynamic data into well typed data then you want the\n"
|
||||
" `gleam/dynamic/decode` module.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" classify(string(\"Hello\"))\n"
|
||||
" // -> \"String\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec classify(dynamic_()) -> binary().
|
||||
classify(Data) ->
|
||||
gleam_stdlib:classify_dynamic(Data).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 36).
|
||||
?DOC(" Create a dynamic value from a bool.\n").
|
||||
-spec bool(boolean()) -> dynamic_().
|
||||
bool(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 44).
|
||||
?DOC(
|
||||
" Create a dynamic value from a string.\n"
|
||||
"\n"
|
||||
" On Erlang this will be a binary string rather than a character list.\n"
|
||||
).
|
||||
-spec string(binary()) -> dynamic_().
|
||||
string(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 50).
|
||||
?DOC(" Create a dynamic value from a float.\n").
|
||||
-spec float(float()) -> dynamic_().
|
||||
float(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 56).
|
||||
?DOC(" Create a dynamic value from an int.\n").
|
||||
-spec int(integer()) -> dynamic_().
|
||||
int(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 62).
|
||||
?DOC(" Create a dynamic value from a bit array.\n").
|
||||
-spec bit_array(bitstring()) -> dynamic_().
|
||||
bit_array(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 68).
|
||||
?DOC(" Create a dynamic value from a list.\n").
|
||||
-spec list(list(dynamic_())) -> dynamic_().
|
||||
list(A) ->
|
||||
gleam_stdlib:identity(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 77).
|
||||
?DOC(
|
||||
" Create a dynamic value from a list, converting it to a sequential runtime\n"
|
||||
" format rather than the regular list format.\n"
|
||||
"\n"
|
||||
" On Erlang this will be a tuple, on JavaScript this will be an array.\n"
|
||||
).
|
||||
-spec array(list(dynamic_())) -> dynamic_().
|
||||
array(A) ->
|
||||
erlang:list_to_tuple(A).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 85).
|
||||
?DOC(
|
||||
" Create a dynamic value made an unordered series of keys and values, where\n"
|
||||
" the keys are unique.\n"
|
||||
"\n"
|
||||
" On Erlang this will be a map, on JavaScript this will be a Gleam dict\n"
|
||||
" object.\n"
|
||||
).
|
||||
-spec properties(list({dynamic_(), dynamic_()})) -> dynamic_().
|
||||
properties(Entries) ->
|
||||
gleam_stdlib:identity(maps:from_list(Entries)).
|
||||
|
||||
-file("src/gleam/dynamic.gleam", 94).
|
||||
?DOC(
|
||||
" A dynamic value representing nothing.\n"
|
||||
"\n"
|
||||
" On Erlang this will be the atom `nil`, on JavaScript this will be\n"
|
||||
" `undefined`.\n"
|
||||
).
|
||||
-spec nil() -> dynamic_().
|
||||
nil() ->
|
||||
gleam_stdlib:identity(nil).
|
||||
1088
build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl
Normal file
1088
build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl
Normal file
File diff suppressed because it is too large
Load diff
744
build/dev/javascript/gleam_stdlib/gleam@float.erl
Normal file
744
build/dev/javascript/gleam_stdlib/gleam@float.erl
Normal file
|
|
@ -0,0 +1,744 @@
|
|||
-module(gleam@float).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/float.gleam").
|
||||
-export([parse/1, to_string/1, compare/2, min/2, max/2, clamp/3, ceiling/1, floor/1, truncate/1, absolute_value/1, loosely_compare/3, loosely_equals/3, power/2, square_root/1, negate/1, round/1, to_precision/2, sum/1, product/1, random/0, modulo/2, divide/2, add/2, multiply/2, subtract/2, logarithm/1, exponential/1]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(
|
||||
" Functions for working with floats.\n"
|
||||
"\n"
|
||||
" ## Float representation\n"
|
||||
"\n"
|
||||
" Floats are represented as 64 bit floating point numbers on both the Erlang\n"
|
||||
" and JavaScript runtimes. The floating point behaviour is native to their\n"
|
||||
" respective runtimes, so their exact behaviour will be slightly different on\n"
|
||||
" the two runtimes.\n"
|
||||
"\n"
|
||||
" ### Infinity and NaN\n"
|
||||
"\n"
|
||||
" Under the JavaScript runtime, exceeding the maximum (or minimum)\n"
|
||||
" representable value for a floating point value will result in Infinity (or\n"
|
||||
" -Infinity). Should you try to divide two infinities you will get NaN as a\n"
|
||||
" result.\n"
|
||||
"\n"
|
||||
" When running on BEAM, exceeding the maximum (or minimum) representable\n"
|
||||
" value for a floating point value will raise an error.\n"
|
||||
"\n"
|
||||
" ## Division by zero\n"
|
||||
"\n"
|
||||
" Gleam runs on the Erlang virtual machine, which does not follow the IEEE\n"
|
||||
" 754 standard for floating point arithmetic and does not have an `Infinity`\n"
|
||||
" value. In Erlang division by zero results in a crash, however Gleam does\n"
|
||||
" not have partial functions and operators in core so instead division by zero\n"
|
||||
" returns zero, a behaviour taken from Pony, Coq, and Lean.\n"
|
||||
"\n"
|
||||
" This may seem unexpected at first, but it is no less mathematically valid\n"
|
||||
" than crashing or returning a special value. Division by zero is undefined\n"
|
||||
" in mathematics.\n"
|
||||
).
|
||||
|
||||
-file("src/gleam/float.gleam", 51).
|
||||
?DOC(
|
||||
" Attempts to parse a string as a `Float`, returning `Error(Nil)` if it was\n"
|
||||
" not possible.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" parse(\"2.3\")\n"
|
||||
" // -> Ok(2.3)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" parse(\"ABC\")\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec parse(binary()) -> {ok, float()} | {error, nil}.
|
||||
parse(String) ->
|
||||
gleam_stdlib:parse_float(String).
|
||||
|
||||
-file("src/gleam/float.gleam", 64).
|
||||
?DOC(
|
||||
" Returns the string representation of the provided `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_string(2.3)\n"
|
||||
" // -> \"2.3\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_string(float()) -> binary().
|
||||
to_string(X) ->
|
||||
gleam_stdlib:float_to_string(X).
|
||||
|
||||
-file("src/gleam/float.gleam", 95).
|
||||
?DOC(
|
||||
" Compares two `Float`s, returning an `Order`:\n"
|
||||
" `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(2.0, 2.3)\n"
|
||||
" // -> Lt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" To handle\n"
|
||||
" [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems)\n"
|
||||
" you may use [`loosely_compare`](#loosely_compare) instead.\n"
|
||||
).
|
||||
-spec compare(float(), float()) -> gleam@order:order().
|
||||
compare(A, B) ->
|
||||
case A =:= B of
|
||||
true ->
|
||||
eq;
|
||||
|
||||
false ->
|
||||
case A < B of
|
||||
true ->
|
||||
lt;
|
||||
|
||||
false ->
|
||||
gt
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 176).
|
||||
?DOC(
|
||||
" Compares two `Float`s, returning the smaller of the two.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" min(2.0, 2.3)\n"
|
||||
" // -> 2.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec min(float(), float()) -> float().
|
||||
min(A, B) ->
|
||||
case A < B of
|
||||
true ->
|
||||
A;
|
||||
|
||||
false ->
|
||||
B
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 192).
|
||||
?DOC(
|
||||
" Compares two `Float`s, returning the larger of the two.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" max(2.0, 2.3)\n"
|
||||
" // -> 2.3\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec max(float(), float()) -> float().
|
||||
max(A, B) ->
|
||||
case A > B of
|
||||
true ->
|
||||
A;
|
||||
|
||||
false ->
|
||||
B
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 75).
|
||||
?DOC(
|
||||
" Restricts a `Float` between a lower and upper bound.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" clamp(1.2, min: 1.4, max: 1.6)\n"
|
||||
" // -> 1.4\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec clamp(float(), float(), float()) -> float().
|
||||
clamp(X, Min_bound, Max_bound) ->
|
||||
_pipe = X,
|
||||
_pipe@1 = min(_pipe, Max_bound),
|
||||
max(_pipe@1, Min_bound).
|
||||
|
||||
-file("src/gleam/float.gleam", 210).
|
||||
?DOC(
|
||||
" Rounds the value to the next highest whole number as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" ceiling(2.3)\n"
|
||||
" // -> 3.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec ceiling(float()) -> float().
|
||||
ceiling(X) ->
|
||||
math:ceil(X).
|
||||
|
||||
-file("src/gleam/float.gleam", 223).
|
||||
?DOC(
|
||||
" Rounds the value to the next lowest whole number as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" floor(2.3)\n"
|
||||
" // -> 2.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec floor(float()) -> float().
|
||||
floor(X) ->
|
||||
math:floor(X).
|
||||
|
||||
-file("src/gleam/float.gleam", 261).
|
||||
?DOC(
|
||||
" Returns the value as an `Int`, truncating all decimal digits.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" truncate(2.4343434847383438)\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec truncate(float()) -> integer().
|
||||
truncate(X) ->
|
||||
erlang:trunc(X).
|
||||
|
||||
-file("src/gleam/float.gleam", 311).
|
||||
?DOC(
|
||||
" Returns the absolute value of the input as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" absolute_value(-12.5)\n"
|
||||
" // -> 12.5\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" absolute_value(10.2)\n"
|
||||
" // -> 10.2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec absolute_value(float()) -> float().
|
||||
absolute_value(X) ->
|
||||
case X >= +0.0 of
|
||||
true ->
|
||||
X;
|
||||
|
||||
false ->
|
||||
+0.0 - X
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 125).
|
||||
?DOC(
|
||||
" Compares two `Float`s within a tolerance, returning an `Order`:\n"
|
||||
" `Lt` for lower than, `Eq` for equals, or `Gt` for greater than.\n"
|
||||
"\n"
|
||||
" This function allows Float comparison while handling\n"
|
||||
" [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n"
|
||||
"\n"
|
||||
" Notice: For `Float`s the tolerance won't be exact:\n"
|
||||
" `5.3 - 5.0` is not exactly `0.3`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" loosely_compare(5.0, with: 5.3, tolerating: 0.5)\n"
|
||||
" // -> Eq\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" If you want to check only for equality you may use\n"
|
||||
" [`loosely_equals`](#loosely_equals) instead.\n"
|
||||
).
|
||||
-spec loosely_compare(float(), float(), float()) -> gleam@order:order().
|
||||
loosely_compare(A, B, Tolerance) ->
|
||||
Difference = absolute_value(A - B),
|
||||
case Difference =< Tolerance of
|
||||
true ->
|
||||
eq;
|
||||
|
||||
false ->
|
||||
compare(A, B)
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 158).
|
||||
?DOC(
|
||||
" Checks for equality of two `Float`s within a tolerance,\n"
|
||||
" returning an `Bool`.\n"
|
||||
"\n"
|
||||
" This function allows Float comparison while handling\n"
|
||||
" [Floating Point Imprecision](https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems).\n"
|
||||
"\n"
|
||||
" Notice: For `Float`s the tolerance won't be exact:\n"
|
||||
" `5.3 - 5.0` is not exactly `0.3`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" loosely_equals(5.0, with: 5.3, tolerating: 0.5)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" loosely_equals(5.0, with: 5.1, tolerating: 0.1)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec loosely_equals(float(), float(), float()) -> boolean().
|
||||
loosely_equals(A, B, Tolerance) ->
|
||||
Difference = absolute_value(A - B),
|
||||
Difference =< Tolerance.
|
||||
|
||||
-file("src/gleam/float.gleam", 348).
|
||||
?DOC(
|
||||
" Returns the results of the base being raised to the power of the\n"
|
||||
" exponent, as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(2.0, -1.0)\n"
|
||||
" // -> Ok(0.5)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(2.0, 2.0)\n"
|
||||
" // -> Ok(4.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(8.0, 1.5)\n"
|
||||
" // -> Ok(22.627416997969522)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 4.0 |> power(of: 2.0)\n"
|
||||
" // -> Ok(16.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(-1.0, 0.5)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec power(float(), float()) -> {ok, float()} | {error, nil}.
|
||||
power(Base, Exponent) ->
|
||||
Fractional = (math:ceil(Exponent) - Exponent) > +0.0,
|
||||
case ((Base < +0.0) andalso Fractional) orelse ((Base =:= +0.0) andalso (Exponent
|
||||
< +0.0)) of
|
||||
true ->
|
||||
{error, nil};
|
||||
|
||||
false ->
|
||||
{ok, math:pow(Base, Exponent)}
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 380).
|
||||
?DOC(
|
||||
" Returns the square root of the input as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" square_root(4.0)\n"
|
||||
" // -> Ok(2.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" square_root(-16.0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec square_root(float()) -> {ok, float()} | {error, nil}.
|
||||
square_root(X) ->
|
||||
power(X, 0.5).
|
||||
|
||||
-file("src/gleam/float.gleam", 393).
|
||||
?DOC(
|
||||
" Returns the negative of the value provided.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(1.0)\n"
|
||||
" // -> -1.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec negate(float()) -> float().
|
||||
negate(X) ->
|
||||
-1.0 * X.
|
||||
|
||||
-file("src/gleam/float.gleam", 240).
|
||||
?DOC(
|
||||
" Rounds the value to the nearest whole number as an `Int`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" round(2.3)\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" round(2.5)\n"
|
||||
" // -> 3\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec round(float()) -> integer().
|
||||
round(X) ->
|
||||
erlang:round(X).
|
||||
|
||||
-file("src/gleam/float.gleam", 280).
|
||||
?DOC(
|
||||
" Converts the value to a given precision as a `Float`.\n"
|
||||
" The precision is the number of allowed decimal places.\n"
|
||||
" Negative precisions are allowed and force rounding\n"
|
||||
" to the nearest tenth, hundredth, thousandth etc.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_precision(2.43434348473, precision: 2)\n"
|
||||
" // -> 2.43\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_precision(547890.453444, precision: -3)\n"
|
||||
" // -> 548000.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_precision(float(), integer()) -> float().
|
||||
to_precision(X, Precision) ->
|
||||
case Precision =< 0 of
|
||||
true ->
|
||||
Factor = math:pow(10.0, erlang:float(- Precision)),
|
||||
erlang:float(erlang:round(case Factor of
|
||||
+0.0 -> +0.0;
|
||||
-0.0 -> -0.0;
|
||||
Gleam@denominator -> X / Gleam@denominator
|
||||
end)) * Factor;
|
||||
|
||||
false ->
|
||||
Factor@1 = math:pow(10.0, erlang:float(Precision)),
|
||||
case Factor@1 of
|
||||
+0.0 -> +0.0;
|
||||
-0.0 -> -0.0;
|
||||
Gleam@denominator@1 -> erlang:float(erlang:round(X * Factor@1))
|
||||
/ Gleam@denominator@1
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 410).
|
||||
-spec sum_loop(list(float()), float()) -> float().
|
||||
sum_loop(Numbers, Initial) ->
|
||||
case Numbers of
|
||||
[First | Rest] ->
|
||||
sum_loop(Rest, First + Initial);
|
||||
|
||||
[] ->
|
||||
Initial
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 406).
|
||||
?DOC(
|
||||
" Sums a list of `Float`s.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" sum([1.0, 2.2, 3.3])\n"
|
||||
" // -> 6.5\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec sum(list(float())) -> float().
|
||||
sum(Numbers) ->
|
||||
sum_loop(Numbers, +0.0).
|
||||
|
||||
-file("src/gleam/float.gleam", 430).
|
||||
-spec product_loop(list(float()), float()) -> float().
|
||||
product_loop(Numbers, Initial) ->
|
||||
case Numbers of
|
||||
[First | Rest] ->
|
||||
product_loop(Rest, First * Initial);
|
||||
|
||||
[] ->
|
||||
Initial
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 426).
|
||||
?DOC(
|
||||
" Multiplies a list of `Float`s and returns the product.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" product([2.5, 3.2, 4.2])\n"
|
||||
" // -> 33.6\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec product(list(float())) -> float().
|
||||
product(Numbers) ->
|
||||
product_loop(Numbers, 1.0).
|
||||
|
||||
-file("src/gleam/float.gleam", 452).
|
||||
?DOC(
|
||||
" Generates a random float between the given zero (inclusive) and one\n"
|
||||
" (exclusive).\n"
|
||||
"\n"
|
||||
" On Erlang this updates the random state in the process dictionary.\n"
|
||||
" See: <https://www.erlang.org/doc/man/rand.html#uniform-0>\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" random()\n"
|
||||
" // -> 0.646355926896028\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec random() -> float().
|
||||
random() ->
|
||||
rand:uniform().
|
||||
|
||||
-file("src/gleam/float.gleam", 481).
|
||||
?DOC(
|
||||
" Computes the modulo of an float division of inputs as a `Result`.\n"
|
||||
"\n"
|
||||
" Returns division of the inputs as a `Result`: If the given divisor equals\n"
|
||||
" `0`, this function returns an `Error`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(13.3, by: 3.3)\n"
|
||||
" // -> Ok(0.1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(-13.3, by: 3.3)\n"
|
||||
" // -> Ok(3.2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(13.3, by: -3.3)\n"
|
||||
" // -> Ok(-3.2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(-13.3, by: -3.3)\n"
|
||||
" // -> Ok(-0.1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec modulo(float(), float()) -> {ok, float()} | {error, nil}.
|
||||
modulo(Dividend, Divisor) ->
|
||||
case Divisor of
|
||||
+0.0 ->
|
||||
{error, nil};
|
||||
|
||||
_ ->
|
||||
{ok, Dividend - (math:floor(case Divisor of
|
||||
+0.0 -> +0.0;
|
||||
-0.0 -> -0.0;
|
||||
Gleam@denominator -> Dividend / Gleam@denominator
|
||||
end) * Divisor)}
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 502).
|
||||
?DOC(
|
||||
" Returns division of the inputs as a `Result`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(0.0, 1.0)\n"
|
||||
" // -> Ok(0.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(1.0, 0.0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec divide(float(), float()) -> {ok, float()} | {error, nil}.
|
||||
divide(A, B) ->
|
||||
case B of
|
||||
+0.0 ->
|
||||
{error, nil};
|
||||
|
||||
B@1 ->
|
||||
{ok, case B@1 of
|
||||
+0.0 -> +0.0;
|
||||
-0.0 -> -0.0;
|
||||
Gleam@denominator -> A / Gleam@denominator
|
||||
end}
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 533).
|
||||
?DOC(
|
||||
" Adds two floats together.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `+.` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" add(1.0, 2.0)\n"
|
||||
" // -> 3.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.fold([1.0, 2.0, 3.0], 0.0, add)\n"
|
||||
" // -> 6.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3.0 |> add(2.0)\n"
|
||||
" // -> 5.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec add(float(), float()) -> float().
|
||||
add(A, B) ->
|
||||
A + B.
|
||||
|
||||
-file("src/gleam/float.gleam", 561).
|
||||
?DOC(
|
||||
" Multiplies two floats together.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `*.` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" multiply(2.0, 4.0)\n"
|
||||
" // -> 8.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.fold([2.0, 3.0, 4.0], 1.0, multiply)\n"
|
||||
" // -> 24.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3.0 |> multiply(2.0)\n"
|
||||
" // -> 6.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec multiply(float(), float()) -> float().
|
||||
multiply(A, B) ->
|
||||
A * B.
|
||||
|
||||
-file("src/gleam/float.gleam", 594).
|
||||
?DOC(
|
||||
" Subtracts one float from another.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `-.` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" subtract(3.0, 1.0)\n"
|
||||
" // -> 2.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.fold([1.0, 2.0, 3.0], 10.0, subtract)\n"
|
||||
" // -> 4.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3.0 |> subtract(_, 2.0)\n"
|
||||
" // -> 1.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3.0 |> subtract(2.0, _)\n"
|
||||
" // -> -1.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec subtract(float(), float()) -> float().
|
||||
subtract(A, B) ->
|
||||
A - B.
|
||||
|
||||
-file("src/gleam/float.gleam", 623).
|
||||
?DOC(
|
||||
" Returns the natural logarithm (base e) of the given as a `Result`. If the\n"
|
||||
" input is less than or equal to 0, returns `Error(Nil)`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" logarithm(1.0)\n"
|
||||
" // -> Ok(0.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" logarithm(2.718281828459045) // e\n"
|
||||
" // -> Ok(1.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" logarithm(0.0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" logarithm(-1.0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec logarithm(float()) -> {ok, float()} | {error, nil}.
|
||||
logarithm(X) ->
|
||||
case X =< +0.0 of
|
||||
true ->
|
||||
{error, nil};
|
||||
|
||||
false ->
|
||||
{ok, math:log(X)}
|
||||
end.
|
||||
|
||||
-file("src/gleam/float.gleam", 661).
|
||||
?DOC(
|
||||
" Returns e (Euler's number) raised to the power of the given exponent, as\n"
|
||||
" a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exponential(0.0)\n"
|
||||
" // -> Ok(1.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exponential(1.0)\n"
|
||||
" // -> Ok(2.718281828459045)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" exponential(-1.0)\n"
|
||||
" // -> Ok(0.36787944117144233)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec exponential(float()) -> float().
|
||||
exponential(X) ->
|
||||
math:exp(X).
|
||||
30
build/dev/javascript/gleam_stdlib/gleam@function.erl
Normal file
30
build/dev/javascript/gleam_stdlib/gleam@function.erl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
-module(gleam@function).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/function.gleam").
|
||||
-export([identity/1, tap/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-file("src/gleam/function.gleam", 3).
|
||||
?DOC(" Takes a single argument and always returns its input value.\n").
|
||||
-spec identity(CLA) -> CLA.
|
||||
identity(X) ->
|
||||
X.
|
||||
|
||||
-file("src/gleam/function.gleam", 12).
|
||||
?DOC(
|
||||
" Takes an argument and a single function, calls that function with that\n"
|
||||
" argument and returns that argument instead of the function return value.\n"
|
||||
"\n"
|
||||
" Useful for running synchronous side effects in a pipeline.\n"
|
||||
).
|
||||
-spec tap(CLB, fun((CLB) -> any())) -> CLB.
|
||||
tap(Arg, Effect) ->
|
||||
Effect(Arg),
|
||||
Arg.
|
||||
986
build/dev/javascript/gleam_stdlib/gleam@int.erl
Normal file
986
build/dev/javascript/gleam_stdlib/gleam@int.erl
Normal file
|
|
@ -0,0 +1,986 @@
|
|||
-module(gleam@int).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/int.gleam").
|
||||
-export([absolute_value/1, parse/1, base_parse/2, to_string/1, to_base_string/2, to_base2/1, to_base8/1, to_base16/1, to_base36/1, to_float/1, power/2, square_root/1, compare/2, min/2, max/2, clamp/3, is_even/1, is_odd/1, negate/1, sum/1, product/1, digits/2, undigits/2, random/1, divide/2, remainder/2, modulo/2, floor_divide/2, add/2, multiply/2, subtract/2, bitwise_and/2, bitwise_not/1, bitwise_or/2, bitwise_exclusive_or/2, bitwise_shift_left/2, bitwise_shift_right/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(
|
||||
" Functions for working with integers.\n"
|
||||
"\n"
|
||||
" ## Division by zero\n"
|
||||
"\n"
|
||||
" In Erlang division by zero results in a crash, however Gleam does not have\n"
|
||||
" partial functions and operators in core so instead division by zero returns\n"
|
||||
" zero, a behaviour taken from Pony, Coq, and Lean.\n"
|
||||
"\n"
|
||||
" This may seem unexpected at first, but it is no less mathematically valid\n"
|
||||
" than crashing or returning a special value. Division by zero is undefined\n"
|
||||
" in mathematics.\n"
|
||||
).
|
||||
|
||||
-file("src/gleam/int.gleam", 30).
|
||||
?DOC(
|
||||
" Returns the absolute value of the input.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" absolute_value(-12)\n"
|
||||
" // -> 12\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" absolute_value(10)\n"
|
||||
" // -> 10\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec absolute_value(integer()) -> integer().
|
||||
absolute_value(X) ->
|
||||
case X >= 0 of
|
||||
true ->
|
||||
X;
|
||||
|
||||
false ->
|
||||
X * -1
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 109).
|
||||
?DOC(
|
||||
" Parses a given string as an int if possible.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" parse(\"2\")\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" parse(\"ABC\")\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec parse(binary()) -> {ok, integer()} | {error, nil}.
|
||||
parse(String) ->
|
||||
gleam_stdlib:parse_int(String).
|
||||
|
||||
-file("src/gleam/int.gleam", 141).
|
||||
?DOC(
|
||||
" Parses a given string as an int in a given base if possible.\n"
|
||||
" Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" base_parse(\"10\", 2)\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" base_parse(\"30\", 16)\n"
|
||||
" // -> Ok(48)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" base_parse(\"1C\", 36)\n"
|
||||
" // -> Ok(48)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" base_parse(\"48\", 1)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" base_parse(\"48\", 37)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec base_parse(binary(), integer()) -> {ok, integer()} | {error, nil}.
|
||||
base_parse(String, Base) ->
|
||||
case (Base >= 2) andalso (Base =< 36) of
|
||||
true ->
|
||||
gleam_stdlib:int_from_base_string(String, Base);
|
||||
|
||||
false ->
|
||||
{error, nil}
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 163).
|
||||
?DOC(
|
||||
" Prints a given int to a string.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_string(2)\n"
|
||||
" // -> \"2\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_string(integer()) -> binary().
|
||||
to_string(X) ->
|
||||
erlang:integer_to_binary(X).
|
||||
|
||||
-file("src/gleam/int.gleam", 196).
|
||||
?DOC(
|
||||
" Prints a given int to a string using the base number provided.\n"
|
||||
" Supports only bases 2 to 36, for values outside of which this function returns an `Error(Nil)`.\n"
|
||||
" For common bases (2, 8, 16, 36), use the `to_baseN` functions.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base_string(2, 2)\n"
|
||||
" // -> Ok(\"10\")\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base_string(48, 16)\n"
|
||||
" // -> Ok(\"30\")\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base_string(48, 36)\n"
|
||||
" // -> Ok(\"1C\")\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base_string(48, 1)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base_string(48, 37)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_base_string(integer(), integer()) -> {ok, binary()} | {error, nil}.
|
||||
to_base_string(X, Base) ->
|
||||
case (Base >= 2) andalso (Base =< 36) of
|
||||
true ->
|
||||
{ok, erlang:integer_to_binary(X, Base)};
|
||||
|
||||
false ->
|
||||
{error, nil}
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 216).
|
||||
?DOC(
|
||||
" Prints a given int to a string using base-2.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base2(2)\n"
|
||||
" // -> \"10\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_base2(integer()) -> binary().
|
||||
to_base2(X) ->
|
||||
erlang:integer_to_binary(X, 2).
|
||||
|
||||
-file("src/gleam/int.gleam", 229).
|
||||
?DOC(
|
||||
" Prints a given int to a string using base-8.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base8(15)\n"
|
||||
" // -> \"17\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_base8(integer()) -> binary().
|
||||
to_base8(X) ->
|
||||
erlang:integer_to_binary(X, 8).
|
||||
|
||||
-file("src/gleam/int.gleam", 242).
|
||||
?DOC(
|
||||
" Prints a given int to a string using base-16.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base16(48)\n"
|
||||
" // -> \"30\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_base16(integer()) -> binary().
|
||||
to_base16(X) ->
|
||||
erlang:integer_to_binary(X, 16).
|
||||
|
||||
-file("src/gleam/int.gleam", 255).
|
||||
?DOC(
|
||||
" Prints a given int to a string using base-36.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_base36(48)\n"
|
||||
" // -> \"1C\"\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_base36(integer()) -> binary().
|
||||
to_base36(X) ->
|
||||
erlang:integer_to_binary(X, 36).
|
||||
|
||||
-file("src/gleam/int.gleam", 280).
|
||||
?DOC(
|
||||
" Takes an int and returns its value as a float.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_float(5)\n"
|
||||
" // -> 5.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_float(0)\n"
|
||||
" // -> 0.0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_float(-3)\n"
|
||||
" // -> -3.0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_float(integer()) -> float().
|
||||
to_float(X) ->
|
||||
erlang:float(X).
|
||||
|
||||
-file("src/gleam/int.gleam", 67).
|
||||
?DOC(
|
||||
" Returns the results of the base being raised to the power of the\n"
|
||||
" exponent, as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(2, -1.0)\n"
|
||||
" // -> Ok(0.5)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(2, 2.0)\n"
|
||||
" // -> Ok(4.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(8, 1.5)\n"
|
||||
" // -> Ok(22.627416997969522)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 4 |> power(of: 2.0)\n"
|
||||
" // -> Ok(16.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" power(-1, 0.5)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec power(integer(), float()) -> {ok, float()} | {error, nil}.
|
||||
power(Base, Exponent) ->
|
||||
_pipe = Base,
|
||||
_pipe@1 = erlang:float(_pipe),
|
||||
gleam@float:power(_pipe@1, Exponent).
|
||||
|
||||
-file("src/gleam/int.gleam", 87).
|
||||
?DOC(
|
||||
" Returns the square root of the input as a `Float`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" square_root(4)\n"
|
||||
" // -> Ok(2.0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" square_root(-16)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec square_root(integer()) -> {ok, float()} | {error, nil}.
|
||||
square_root(X) ->
|
||||
_pipe = X,
|
||||
_pipe@1 = erlang:float(_pipe),
|
||||
gleam@float:square_root(_pipe@1).
|
||||
|
||||
-file("src/gleam/int.gleam", 316).
|
||||
?DOC(
|
||||
" Compares two ints, returning an order.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(2, 3)\n"
|
||||
" // -> Lt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(4, 3)\n"
|
||||
" // -> Gt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(3, 3)\n"
|
||||
" // -> Eq\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec compare(integer(), integer()) -> gleam@order:order().
|
||||
compare(A, B) ->
|
||||
case A =:= B of
|
||||
true ->
|
||||
eq;
|
||||
|
||||
false ->
|
||||
case A < B of
|
||||
true ->
|
||||
lt;
|
||||
|
||||
false ->
|
||||
gt
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 336).
|
||||
?DOC(
|
||||
" Compares two ints, returning the smaller of the two.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" min(2, 3)\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec min(integer(), integer()) -> integer().
|
||||
min(A, B) ->
|
||||
case A < B of
|
||||
true ->
|
||||
A;
|
||||
|
||||
false ->
|
||||
B
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 352).
|
||||
?DOC(
|
||||
" Compares two ints, returning the larger of the two.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" max(2, 3)\n"
|
||||
" // -> 3\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec max(integer(), integer()) -> integer().
|
||||
max(A, B) ->
|
||||
case A > B of
|
||||
true ->
|
||||
A;
|
||||
|
||||
false ->
|
||||
B
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 291).
|
||||
?DOC(
|
||||
" Restricts an int between a lower and upper bound.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" clamp(40, min: 50, max: 60)\n"
|
||||
" // -> 50\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec clamp(integer(), integer(), integer()) -> integer().
|
||||
clamp(X, Min_bound, Max_bound) ->
|
||||
_pipe = X,
|
||||
_pipe@1 = min(_pipe, Max_bound),
|
||||
max(_pipe@1, Min_bound).
|
||||
|
||||
-file("src/gleam/int.gleam", 373).
|
||||
?DOC(
|
||||
" Returns whether the value provided is even.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_even(2)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_even(3)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_even(integer()) -> boolean().
|
||||
is_even(X) ->
|
||||
(X rem 2) =:= 0.
|
||||
|
||||
-file("src/gleam/int.gleam", 391).
|
||||
?DOC(
|
||||
" Returns whether the value provided is odd.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_odd(3)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_odd(2)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_odd(integer()) -> boolean().
|
||||
is_odd(X) ->
|
||||
(X rem 2) /= 0.
|
||||
|
||||
-file("src/gleam/int.gleam", 404).
|
||||
?DOC(
|
||||
" Returns the negative of the value provided.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(1)\n"
|
||||
" // -> -1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec negate(integer()) -> integer().
|
||||
negate(X) ->
|
||||
-1 * X.
|
||||
|
||||
-file("src/gleam/int.gleam", 421).
|
||||
-spec sum_loop(list(integer()), integer()) -> integer().
|
||||
sum_loop(Numbers, Initial) ->
|
||||
case Numbers of
|
||||
[First | Rest] ->
|
||||
sum_loop(Rest, First + Initial);
|
||||
|
||||
[] ->
|
||||
Initial
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 417).
|
||||
?DOC(
|
||||
" Sums a list of ints.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" sum([1, 2, 3])\n"
|
||||
" // -> 6\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec sum(list(integer())) -> integer().
|
||||
sum(Numbers) ->
|
||||
sum_loop(Numbers, 0).
|
||||
|
||||
-file("src/gleam/int.gleam", 441).
|
||||
-spec product_loop(list(integer()), integer()) -> integer().
|
||||
product_loop(Numbers, Initial) ->
|
||||
case Numbers of
|
||||
[First | Rest] ->
|
||||
product_loop(Rest, First * Initial);
|
||||
|
||||
[] ->
|
||||
Initial
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 437).
|
||||
?DOC(
|
||||
" Multiplies a list of ints and returns the product.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" product([2, 3, 4])\n"
|
||||
" // -> 24\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec product(list(integer())) -> integer().
|
||||
product(Numbers) ->
|
||||
product_loop(Numbers, 1).
|
||||
|
||||
-file("src/gleam/int.gleam", 456).
|
||||
-spec digits_loop(integer(), integer(), list(integer())) -> list(integer()).
|
||||
digits_loop(X, Base, Acc) ->
|
||||
case absolute_value(X) < Base of
|
||||
true ->
|
||||
[X | Acc];
|
||||
|
||||
false ->
|
||||
digits_loop(case Base of
|
||||
0 -> 0;
|
||||
Gleam@denominator -> X div Gleam@denominator
|
||||
end, Base, [case Base of
|
||||
0 -> 0;
|
||||
Gleam@denominator@1 -> X rem Gleam@denominator@1
|
||||
end | Acc])
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 449).
|
||||
-spec digits(integer(), integer()) -> {ok, list(integer())} | {error, nil}.
|
||||
digits(X, Base) ->
|
||||
case Base < 2 of
|
||||
true ->
|
||||
{error, nil};
|
||||
|
||||
false ->
|
||||
{ok, digits_loop(X, Base, [])}
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 471).
|
||||
-spec undigits_loop(list(integer()), integer(), integer()) -> {ok, integer()} |
|
||||
{error, nil}.
|
||||
undigits_loop(Numbers, Base, Acc) ->
|
||||
case Numbers of
|
||||
[] ->
|
||||
{ok, Acc};
|
||||
|
||||
[Digit | _] when Digit >= Base ->
|
||||
{error, nil};
|
||||
|
||||
[Digit@1 | Rest] ->
|
||||
undigits_loop(Rest, Base, (Acc * Base) + Digit@1)
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 464).
|
||||
-spec undigits(list(integer()), integer()) -> {ok, integer()} | {error, nil}.
|
||||
undigits(Numbers, Base) ->
|
||||
case Base < 2 of
|
||||
true ->
|
||||
{error, nil};
|
||||
|
||||
false ->
|
||||
undigits_loop(Numbers, Base, 0)
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 500).
|
||||
?DOC(
|
||||
" Generates a random int between zero and the given maximum.\n"
|
||||
"\n"
|
||||
" The lower number is inclusive, the upper number is exclusive.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" random(10)\n"
|
||||
" // -> 4\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" random(1)\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" random(-1)\n"
|
||||
" // -> -1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec random(integer()) -> integer().
|
||||
random(Max) ->
|
||||
_pipe = (rand:uniform() * erlang:float(Max)),
|
||||
_pipe@1 = math:floor(_pipe),
|
||||
erlang:round(_pipe@1).
|
||||
|
||||
-file("src/gleam/int.gleam", 533).
|
||||
?DOC(
|
||||
" Performs a truncated integer division.\n"
|
||||
"\n"
|
||||
" Returns division of the inputs as a `Result`: If the given divisor equals\n"
|
||||
" `0`, this function returns an `Error`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(0, 1)\n"
|
||||
" // -> Ok(0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(1, 0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(5, 2)\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" divide(-99, 2)\n"
|
||||
" // -> Ok(-49)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec divide(integer(), integer()) -> {ok, integer()} | {error, nil}.
|
||||
divide(Dividend, Divisor) ->
|
||||
case Divisor of
|
||||
0 ->
|
||||
{error, nil};
|
||||
|
||||
Divisor@1 ->
|
||||
{ok, case Divisor@1 of
|
||||
0 -> 0;
|
||||
Gleam@denominator -> Dividend div Gleam@denominator
|
||||
end}
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 585).
|
||||
?DOC(
|
||||
" Computes the remainder of an integer division of inputs as a `Result`.\n"
|
||||
"\n"
|
||||
" Returns division of the inputs as a `Result`: If the given divisor equals\n"
|
||||
" `0`, this function returns an `Error`.\n"
|
||||
"\n"
|
||||
" Most the time you will want to use the `%` operator instead of this\n"
|
||||
" function.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(3, 2)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(1, 0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(10, -1)\n"
|
||||
" // -> Ok(0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(13, by: 3)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(-13, by: 3)\n"
|
||||
" // -> Ok(-1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(13, by: -3)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" remainder(-13, by: -3)\n"
|
||||
" // -> Ok(-1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec remainder(integer(), integer()) -> {ok, integer()} | {error, nil}.
|
||||
remainder(Dividend, Divisor) ->
|
||||
case Divisor of
|
||||
0 ->
|
||||
{error, nil};
|
||||
|
||||
Divisor@1 ->
|
||||
{ok, case Divisor@1 of
|
||||
0 -> 0;
|
||||
Gleam@denominator -> Dividend rem Gleam@denominator
|
||||
end}
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 627).
|
||||
?DOC(
|
||||
" Computes the modulo of an integer division of inputs as a `Result`.\n"
|
||||
"\n"
|
||||
" Returns division of the inputs as a `Result`: If the given divisor equals\n"
|
||||
" `0`, this function returns an `Error`.\n"
|
||||
"\n"
|
||||
" Most the time you will want to use the `%` operator instead of this\n"
|
||||
" function.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(3, 2)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(1, 0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(10, -1)\n"
|
||||
" // -> Ok(0)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(13, by: 3)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" modulo(-13, by: 3)\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec modulo(integer(), integer()) -> {ok, integer()} | {error, nil}.
|
||||
modulo(Dividend, Divisor) ->
|
||||
case Divisor of
|
||||
0 ->
|
||||
{error, nil};
|
||||
|
||||
_ ->
|
||||
Remainder = case Divisor of
|
||||
0 -> 0;
|
||||
Gleam@denominator -> Dividend rem Gleam@denominator
|
||||
end,
|
||||
case (Remainder * Divisor) < 0 of
|
||||
true ->
|
||||
{ok, Remainder + Divisor};
|
||||
|
||||
false ->
|
||||
{ok, Remainder}
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 671).
|
||||
?DOC(
|
||||
" Performs a *floored* integer division, which means that the result will\n"
|
||||
" always be rounded towards negative infinity.\n"
|
||||
"\n"
|
||||
" If you want to perform truncated integer division (rounding towards zero),\n"
|
||||
" use `int.divide()` or the `/` operator instead.\n"
|
||||
"\n"
|
||||
" Returns division of the inputs as a `Result`: If the given divisor equals\n"
|
||||
" `0`, this function returns an `Error`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" floor_divide(1, 0)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" floor_divide(5, 2)\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" floor_divide(6, -4)\n"
|
||||
" // -> Ok(-2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" floor_divide(-99, 2)\n"
|
||||
" // -> Ok(-50)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec floor_divide(integer(), integer()) -> {ok, integer()} | {error, nil}.
|
||||
floor_divide(Dividend, Divisor) ->
|
||||
case Divisor of
|
||||
0 ->
|
||||
{error, nil};
|
||||
|
||||
Divisor@1 ->
|
||||
case ((Dividend * Divisor@1) < 0) andalso ((case Divisor@1 of
|
||||
0 -> 0;
|
||||
Gleam@denominator -> Dividend rem Gleam@denominator
|
||||
end) /= 0) of
|
||||
true ->
|
||||
{ok, (case Divisor@1 of
|
||||
0 -> 0;
|
||||
Gleam@denominator@1 -> Dividend div Gleam@denominator@1
|
||||
end) - 1};
|
||||
|
||||
false ->
|
||||
{ok, case Divisor@1 of
|
||||
0 -> 0;
|
||||
Gleam@denominator@2 -> Dividend div Gleam@denominator@2
|
||||
end}
|
||||
end
|
||||
end.
|
||||
|
||||
-file("src/gleam/int.gleam", 705).
|
||||
?DOC(
|
||||
" Adds two integers together.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `+` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" add(1, 2)\n"
|
||||
" // -> 3\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
" list.fold([1, 2, 3], 0, add)\n"
|
||||
" // -> 6\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3 |> add(2)\n"
|
||||
" // -> 5\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec add(integer(), integer()) -> integer().
|
||||
add(A, B) ->
|
||||
A + B.
|
||||
|
||||
-file("src/gleam/int.gleam", 733).
|
||||
?DOC(
|
||||
" Multiplies two integers together.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `*` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" multiply(2, 4)\n"
|
||||
" // -> 8\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.fold([2, 3, 4], 1, multiply)\n"
|
||||
" // -> 24\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3 |> multiply(2)\n"
|
||||
" // -> 6\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec multiply(integer(), integer()) -> integer().
|
||||
multiply(A, B) ->
|
||||
A * B.
|
||||
|
||||
-file("src/gleam/int.gleam", 766).
|
||||
?DOC(
|
||||
" Subtracts one int from another.\n"
|
||||
"\n"
|
||||
" It's the function equivalent of the `-` operator.\n"
|
||||
" This function is useful in higher order functions or pipes.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" subtract(3, 1)\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.fold([1, 2, 3], 10, subtract)\n"
|
||||
" // -> 4\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3 |> subtract(2)\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" 3 |> subtract(2, _)\n"
|
||||
" // -> -1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec subtract(integer(), integer()) -> integer().
|
||||
subtract(A, B) ->
|
||||
A - B.
|
||||
|
||||
-file("src/gleam/int.gleam", 778).
|
||||
?DOC(
|
||||
" Calculates the bitwise AND of its arguments.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_and(integer(), integer()) -> integer().
|
||||
bitwise_and(X, Y) ->
|
||||
erlang:'band'(X, Y).
|
||||
|
||||
-file("src/gleam/int.gleam", 788).
|
||||
?DOC(
|
||||
" Calculates the bitwise NOT of its argument.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_not(integer()) -> integer().
|
||||
bitwise_not(X) ->
|
||||
erlang:'bnot'(X).
|
||||
|
||||
-file("src/gleam/int.gleam", 798).
|
||||
?DOC(
|
||||
" Calculates the bitwise OR of its arguments.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_or(integer(), integer()) -> integer().
|
||||
bitwise_or(X, Y) ->
|
||||
erlang:'bor'(X, Y).
|
||||
|
||||
-file("src/gleam/int.gleam", 808).
|
||||
?DOC(
|
||||
" Calculates the bitwise XOR of its arguments.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_exclusive_or(integer(), integer()) -> integer().
|
||||
bitwise_exclusive_or(X, Y) ->
|
||||
erlang:'bxor'(X, Y).
|
||||
|
||||
-file("src/gleam/int.gleam", 818).
|
||||
?DOC(
|
||||
" Calculates the result of an arithmetic left bitshift.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_shift_left(integer(), integer()) -> integer().
|
||||
bitwise_shift_left(X, Y) ->
|
||||
erlang:'bsl'(X, Y).
|
||||
|
||||
-file("src/gleam/int.gleam", 828).
|
||||
?DOC(
|
||||
" Calculates the result of an arithmetic right bitshift.\n"
|
||||
"\n"
|
||||
" The exact behaviour of this function depends on the target platform.\n"
|
||||
" On Erlang it is equivalent to bitwise operations on ints, on JavaScript it\n"
|
||||
" is equivalent to bitwise operations on big-ints.\n"
|
||||
).
|
||||
-spec bitwise_shift_right(integer(), integer()) -> integer().
|
||||
bitwise_shift_right(X, Y) ->
|
||||
erlang:'bsr'(X, Y).
|
||||
80
build/dev/javascript/gleam_stdlib/gleam@io.erl
Normal file
80
build/dev/javascript/gleam_stdlib/gleam@io.erl
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
-module(gleam@io).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/io.gleam").
|
||||
-export([print/1, print_error/1, println/1, println_error/1]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-file("src/gleam/io.gleam", 15).
|
||||
?DOC(
|
||||
" Writes a string to standard output (stdout).\n"
|
||||
"\n"
|
||||
" If you want your output to be printed on its own line see `println`.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" io.print(\"Hi mum\")\n"
|
||||
" // -> Nil\n"
|
||||
" // Hi mum\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec print(binary()) -> nil.
|
||||
print(String) ->
|
||||
gleam_stdlib:print(String).
|
||||
|
||||
-file("src/gleam/io.gleam", 31).
|
||||
?DOC(
|
||||
" Writes a string to standard error (stderr).\n"
|
||||
"\n"
|
||||
" If you want your output to be printed on its own line see `println_error`.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```\n"
|
||||
" io.print_error(\"Hi pop\")\n"
|
||||
" // -> Nil\n"
|
||||
" // Hi pop\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec print_error(binary()) -> nil.
|
||||
print_error(String) ->
|
||||
gleam_stdlib:print_error(String).
|
||||
|
||||
-file("src/gleam/io.gleam", 45).
|
||||
?DOC(
|
||||
" Writes a string to standard output (stdout), appending a newline to the end.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" io.println(\"Hi mum\")\n"
|
||||
" // -> Nil\n"
|
||||
" // Hi mum\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec println(binary()) -> nil.
|
||||
println(String) ->
|
||||
gleam_stdlib:println(String).
|
||||
|
||||
-file("src/gleam/io.gleam", 59).
|
||||
?DOC(
|
||||
" Writes a string to standard error (stderr), appending a newline to the end.\n"
|
||||
"\n"
|
||||
" ## Example\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" io.println_error(\"Hi pop\")\n"
|
||||
" // -> Nil\n"
|
||||
" // Hi pop\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec println_error(binary()) -> nil.
|
||||
println_error(String) ->
|
||||
gleam_stdlib:println_error(String).
|
||||
2873
build/dev/javascript/gleam_stdlib/gleam@list.erl
Normal file
2873
build/dev/javascript/gleam_stdlib/gleam@list.erl
Normal file
File diff suppressed because it is too large
Load diff
413
build/dev/javascript/gleam_stdlib/gleam@option.erl
Normal file
413
build/dev/javascript/gleam_stdlib/gleam@option.erl
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
-module(gleam@option).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/option.gleam").
|
||||
-export([all/1, is_some/1, is_none/1, to_result/2, from_result/1, unwrap/2, lazy_unwrap/2, map/2, flatten/1, then/2, 'or'/2, lazy_or/2, values/1]).
|
||||
-export_type([option/1]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-type option(FG) :: {some, FG} | none.
|
||||
|
||||
-file("src/gleam/option.gleam", 59).
|
||||
-spec reverse_and_prepend(list(FV), list(FV)) -> list(FV).
|
||||
reverse_and_prepend(Prefix, Suffix) ->
|
||||
case Prefix of
|
||||
[] ->
|
||||
Suffix;
|
||||
|
||||
[First | Rest] ->
|
||||
reverse_and_prepend(Rest, [First | Suffix])
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 44).
|
||||
-spec all_loop(list(option(FM)), list(FM)) -> option(list(FM)).
|
||||
all_loop(List, Acc) ->
|
||||
case List of
|
||||
[] ->
|
||||
{some, lists:reverse(Acc)};
|
||||
|
||||
[none | _] ->
|
||||
none;
|
||||
|
||||
[{some, First} | Rest] ->
|
||||
all_loop(Rest, [First | Acc])
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 40).
|
||||
?DOC(
|
||||
" Combines a list of `Option`s into a single `Option`.\n"
|
||||
" If all elements in the list are `Some` then returns a `Some` holding the list of values.\n"
|
||||
" If any element is `None` then returns`None`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" all([Some(1), Some(2)])\n"
|
||||
" // -> Some([1, 2])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" all([Some(1), None])\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec all(list(option(FH))) -> option(list(FH)).
|
||||
all(List) ->
|
||||
all_loop(List, []).
|
||||
|
||||
-file("src/gleam/option.gleam", 80).
|
||||
?DOC(
|
||||
" Checks whether the `Option` is a `Some` value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_some(Some(1))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_some(None)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_some(option(any())) -> boolean().
|
||||
is_some(Option) ->
|
||||
Option /= none.
|
||||
|
||||
-file("src/gleam/option.gleam", 98).
|
||||
?DOC(
|
||||
" Checks whether the `Option` is a `None` value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_none(Some(1))\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_none(None)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_none(option(any())) -> boolean().
|
||||
is_none(Option) ->
|
||||
Option =:= none.
|
||||
|
||||
-file("src/gleam/option.gleam", 116).
|
||||
?DOC(
|
||||
" Converts an `Option` type to a `Result` type.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_result(Some(1), \"some_error\")\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_result(None, \"some_error\")\n"
|
||||
" // -> Error(\"some_error\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_result(option(GD), GG) -> {ok, GD} | {error, GG}.
|
||||
to_result(Option, E) ->
|
||||
case Option of
|
||||
{some, A} ->
|
||||
{ok, A};
|
||||
|
||||
none ->
|
||||
{error, E}
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 137).
|
||||
?DOC(
|
||||
" Converts a `Result` type to an `Option` type.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_result(Ok(1))\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_result(Error(\"some_error\"))\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec from_result({ok, GJ} | {error, any()}) -> option(GJ).
|
||||
from_result(Result) ->
|
||||
case Result of
|
||||
{ok, A} ->
|
||||
{some, A};
|
||||
|
||||
{error, _} ->
|
||||
none
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 158).
|
||||
?DOC(
|
||||
" Extracts the value from an `Option`, returning a default value if there is none.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap(Some(1), 0)\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap(None, 0)\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec unwrap(option(GO), GO) -> GO.
|
||||
unwrap(Option, Default) ->
|
||||
case Option of
|
||||
{some, X} ->
|
||||
X;
|
||||
|
||||
none ->
|
||||
Default
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 179).
|
||||
?DOC(
|
||||
" Extracts the value from an `Option`, evaluating the default function if the option is `None`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_unwrap(Some(1), fn() { 0 })\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_unwrap(None, fn() { 0 })\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_unwrap(option(GQ), fun(() -> GQ)) -> GQ.
|
||||
lazy_unwrap(Option, Default) ->
|
||||
case Option of
|
||||
{some, X} ->
|
||||
X;
|
||||
|
||||
none ->
|
||||
Default()
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 204).
|
||||
?DOC(
|
||||
" Updates a value held within the `Some` of an `Option` by calling a given function\n"
|
||||
" on it.\n"
|
||||
"\n"
|
||||
" If the `Option` is a `None` rather than `Some`, the function is not called and the\n"
|
||||
" `Option` stays the same.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map(over: Some(1), with: fn(x) { x + 1 })\n"
|
||||
" // -> Some(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map(over: None, with: fn(x) { x + 1 })\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map(option(GS), fun((GS) -> GU)) -> option(GU).
|
||||
map(Option, Fun) ->
|
||||
case Option of
|
||||
{some, X} ->
|
||||
{some, Fun(X)};
|
||||
|
||||
none ->
|
||||
none
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 230).
|
||||
?DOC(
|
||||
" Merges a nested `Option` into a single layer.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(Some(Some(1)))\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(Some(None))\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(None)\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec flatten(option(option(GW))) -> option(GW).
|
||||
flatten(Option) ->
|
||||
case Option of
|
||||
{some, X} ->
|
||||
X;
|
||||
|
||||
none ->
|
||||
none
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 269).
|
||||
?DOC(
|
||||
" Updates a value held within the `Some` of an `Option` by calling a given function\n"
|
||||
" on it, where the given function also returns an `Option`. The two options are\n"
|
||||
" then merged together into one `Option`.\n"
|
||||
"\n"
|
||||
" If the `Option` is a `None` rather than `Some` the function is not called and the\n"
|
||||
" option stays the same.\n"
|
||||
"\n"
|
||||
" This function is the equivalent of calling `map` followed by `flatten`, and\n"
|
||||
" it is useful for chaining together multiple functions that return `Option`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" then(Some(1), fn(x) { Some(x + 1) })\n"
|
||||
" // -> Some(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" then(Some(1), fn(x) { Some(#(\"a\", x)) })\n"
|
||||
" // -> Some(#(\"a\", 1))\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" then(Some(1), fn(_) { None })\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" then(None, fn(x) { Some(x + 1) })\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec then(option(HA), fun((HA) -> option(HC))) -> option(HC).
|
||||
then(Option, Fun) ->
|
||||
case Option of
|
||||
{some, X} ->
|
||||
Fun(X);
|
||||
|
||||
none ->
|
||||
none
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 300).
|
||||
?DOC(
|
||||
" Returns the first value if it is `Some`, otherwise returns the second value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Some(1), Some(2))\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Some(1), None)\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(None, Some(2))\n"
|
||||
" // -> Some(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(None, None)\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec 'or'(option(HF), option(HF)) -> option(HF).
|
||||
'or'(First, Second) ->
|
||||
case First of
|
||||
{some, _} ->
|
||||
First;
|
||||
|
||||
none ->
|
||||
Second
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 331).
|
||||
?DOC(
|
||||
" Returns the first value if it is `Some`, otherwise evaluates the given function for a fallback value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Some(1), fn() { Some(2) })\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Some(1), fn() { None })\n"
|
||||
" // -> Some(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(None, fn() { Some(2) })\n"
|
||||
" // -> Some(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(None, fn() { None })\n"
|
||||
" // -> None\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_or(option(HJ), fun(() -> option(HJ))) -> option(HJ).
|
||||
lazy_or(First, Second) ->
|
||||
case First of
|
||||
{some, _} ->
|
||||
First;
|
||||
|
||||
none ->
|
||||
Second()
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 352).
|
||||
-spec values_loop(list(option(HR)), list(HR)) -> list(HR).
|
||||
values_loop(List, Acc) ->
|
||||
case List of
|
||||
[] ->
|
||||
lists:reverse(Acc);
|
||||
|
||||
[none | Rest] ->
|
||||
values_loop(Rest, Acc);
|
||||
|
||||
[{some, First} | Rest@1] ->
|
||||
values_loop(Rest@1, [First | Acc])
|
||||
end.
|
||||
|
||||
-file("src/gleam/option.gleam", 348).
|
||||
?DOC(
|
||||
" Given a list of `Option`s,\n"
|
||||
" returns only the values inside `Some`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" values([Some(1), None, Some(3)])\n"
|
||||
" // -> [1, 3]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec values(list(option(HN))) -> list(HN).
|
||||
values(Options) ->
|
||||
values_loop(Options, []).
|
||||
200
build/dev/javascript/gleam_stdlib/gleam@order.erl
Normal file
200
build/dev/javascript/gleam_stdlib/gleam@order.erl
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
-module(gleam@order).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/order.gleam").
|
||||
-export([negate/1, to_int/1, compare/2, reverse/1, break_tie/2, lazy_break_tie/2]).
|
||||
-export_type([order/0]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-type order() :: lt | eq | gt.
|
||||
|
||||
-file("src/gleam/order.gleam", 35).
|
||||
?DOC(
|
||||
" Inverts an order, so less-than becomes greater-than and greater-than\n"
|
||||
" becomes less-than.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(Lt)\n"
|
||||
" // -> Gt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(Eq)\n"
|
||||
" // -> Eq\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" negate(Gt)\n"
|
||||
" // -> Lt\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec negate(order()) -> order().
|
||||
negate(Order) ->
|
||||
case Order of
|
||||
lt ->
|
||||
gt;
|
||||
|
||||
eq ->
|
||||
eq;
|
||||
|
||||
gt ->
|
||||
lt
|
||||
end.
|
||||
|
||||
-file("src/gleam/order.gleam", 62).
|
||||
?DOC(
|
||||
" Produces a numeric representation of the order.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_int(Lt)\n"
|
||||
" // -> -1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_int(Eq)\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" to_int(Gt)\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_int(order()) -> integer().
|
||||
to_int(Order) ->
|
||||
case Order of
|
||||
lt ->
|
||||
-1;
|
||||
|
||||
eq ->
|
||||
0;
|
||||
|
||||
gt ->
|
||||
1
|
||||
end.
|
||||
|
||||
-file("src/gleam/order.gleam", 79).
|
||||
?DOC(
|
||||
" Compares two `Order` values to one another, producing a new `Order`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" compare(Eq, with: Lt)\n"
|
||||
" // -> Gt\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec compare(order(), order()) -> order().
|
||||
compare(A, B) ->
|
||||
case {A, B} of
|
||||
{X, Y} when X =:= Y ->
|
||||
eq;
|
||||
|
||||
{lt, _} ->
|
||||
lt;
|
||||
|
||||
{eq, gt} ->
|
||||
lt;
|
||||
|
||||
{_, _} ->
|
||||
gt
|
||||
end.
|
||||
|
||||
-file("src/gleam/order.gleam", 100).
|
||||
?DOC(
|
||||
" Inverts an ordering function, so less-than becomes greater-than and greater-than\n"
|
||||
" becomes less-than.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" list.sort([1, 5, 4], by: reverse(int.compare))\n"
|
||||
" // -> [5, 4, 1]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec reverse(fun((I, I) -> order())) -> fun((I, I) -> order()).
|
||||
reverse(Orderer) ->
|
||||
fun(A, B) -> Orderer(B, A) end.
|
||||
|
||||
-file("src/gleam/order.gleam", 122).
|
||||
?DOC(
|
||||
" Return a fallback `Order` in case the first argument is `Eq`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" break_tie(in: int.compare(1, 1), with: Lt)\n"
|
||||
" // -> Lt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" break_tie(in: int.compare(1, 0), with: Eq)\n"
|
||||
" // -> Gt\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec break_tie(order(), order()) -> order().
|
||||
break_tie(Order, Other) ->
|
||||
case Order of
|
||||
lt ->
|
||||
Order;
|
||||
|
||||
gt ->
|
||||
Order;
|
||||
|
||||
eq ->
|
||||
Other
|
||||
end.
|
||||
|
||||
-file("src/gleam/order.gleam", 151).
|
||||
?DOC(
|
||||
" Invokes a fallback function returning an `Order` in case the first argument\n"
|
||||
" is `Eq`.\n"
|
||||
"\n"
|
||||
" This can be useful when the fallback comparison might be expensive and it\n"
|
||||
" needs to be delayed until strictly necessary.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" lazy_break_tie(in: int.compare(1, 1), with: fn() { Lt })\n"
|
||||
" // -> Lt\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" lazy_break_tie(in: int.compare(1, 0), with: fn() { Eq })\n"
|
||||
" // -> Gt\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_break_tie(order(), fun(() -> order())) -> order().
|
||||
lazy_break_tie(Order, Comparison) ->
|
||||
case Order of
|
||||
lt ->
|
||||
Order;
|
||||
|
||||
gt ->
|
||||
Order;
|
||||
|
||||
eq ->
|
||||
Comparison()
|
||||
end.
|
||||
110
build/dev/javascript/gleam_stdlib/gleam@pair.erl
Normal file
110
build/dev/javascript/gleam_stdlib/gleam@pair.erl
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
-module(gleam@pair).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/pair.gleam").
|
||||
-export([first/1, second/1, swap/1, map_first/2, map_second/2, new/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-file("src/gleam/pair.gleam", 10).
|
||||
?DOC(
|
||||
" Returns the first element in a pair.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" first(#(1, 2))\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec first({CLF, any()}) -> CLF.
|
||||
first(Pair) ->
|
||||
{A, _} = Pair,
|
||||
A.
|
||||
|
||||
-file("src/gleam/pair.gleam", 24).
|
||||
?DOC(
|
||||
" Returns the second element in a pair.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" second(#(1, 2))\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec second({any(), CLI}) -> CLI.
|
||||
second(Pair) ->
|
||||
{_, A} = Pair,
|
||||
A.
|
||||
|
||||
-file("src/gleam/pair.gleam", 38).
|
||||
?DOC(
|
||||
" Returns a new pair with the elements swapped.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" swap(#(1, 2))\n"
|
||||
" // -> #(2, 1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec swap({CLJ, CLK}) -> {CLK, CLJ}.
|
||||
swap(Pair) ->
|
||||
{A, B} = Pair,
|
||||
{B, A}.
|
||||
|
||||
-file("src/gleam/pair.gleam", 53).
|
||||
?DOC(
|
||||
" Returns a new pair with the first element having had `with` applied to\n"
|
||||
" it.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" #(1, 2) |> map_first(fn(n) { n * 2 })\n"
|
||||
" // -> #(2, 2)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map_first({CLL, CLM}, fun((CLL) -> CLN)) -> {CLN, CLM}.
|
||||
map_first(Pair, Fun) ->
|
||||
{A, B} = Pair,
|
||||
{Fun(A), B}.
|
||||
|
||||
-file("src/gleam/pair.gleam", 68).
|
||||
?DOC(
|
||||
" Returns a new pair with the second element having had `with` applied to\n"
|
||||
" it.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" #(1, 2) |> map_second(fn(n) { n * 2 })\n"
|
||||
" // -> #(1, 4)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map_second({CLO, CLP}, fun((CLP) -> CLQ)) -> {CLO, CLQ}.
|
||||
map_second(Pair, Fun) ->
|
||||
{A, B} = Pair,
|
||||
{A, Fun(B)}.
|
||||
|
||||
-file("src/gleam/pair.gleam", 83).
|
||||
?DOC(
|
||||
" Returns a new pair with the given elements. This can also be done using the dedicated\n"
|
||||
" syntax instead: `new(1, 2) == #(1, 2)`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new(1, 2)\n"
|
||||
" // -> #(1, 2)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec new(CLR, CLS) -> {CLR, CLS}.
|
||||
new(First, Second) ->
|
||||
{First, Second}.
|
||||
550
build/dev/javascript/gleam_stdlib/gleam@result.erl
Normal file
550
build/dev/javascript/gleam_stdlib/gleam@result.erl
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
-module(gleam@result).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/result.gleam").
|
||||
-export([is_ok/1, is_error/1, map/2, map_error/2, flatten/1, 'try'/2, then/2, unwrap/2, lazy_unwrap/2, unwrap_error/2, unwrap_both/1, 'or'/2, lazy_or/2, all/1, partition/1, replace/2, replace_error/2, values/1, try_recover/2]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
?MODULEDOC(
|
||||
" Result represents the result of something that may succeed or not.\n"
|
||||
" `Ok` means it was successful, `Error` means it was not successful.\n"
|
||||
).
|
||||
|
||||
-file("src/gleam/result.gleam", 20).
|
||||
?DOC(
|
||||
" Checks whether the result is an `Ok` value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_ok(Ok(1))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_ok(Error(Nil))\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_ok({ok, any()} | {error, any()}) -> boolean().
|
||||
is_ok(Result) ->
|
||||
case Result of
|
||||
{error, _} ->
|
||||
false;
|
||||
|
||||
{ok, _} ->
|
||||
true
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 41).
|
||||
?DOC(
|
||||
" Checks whether the result is an `Error` value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_error(Ok(1))\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_error(Error(Nil))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_error({ok, any()} | {error, any()}) -> boolean().
|
||||
is_error(Result) ->
|
||||
case Result of
|
||||
{ok, _} ->
|
||||
false;
|
||||
|
||||
{error, _} ->
|
||||
true
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 66).
|
||||
?DOC(
|
||||
" Updates a value held within the `Ok` of a result by calling a given function\n"
|
||||
" on it.\n"
|
||||
"\n"
|
||||
" If the result is an `Error` rather than `Ok` the function is not called and the\n"
|
||||
" result stays the same.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map(over: Ok(1), with: fn(x) { x + 1 })\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map(over: Error(1), with: fn(x) { x + 1 })\n"
|
||||
" // -> Error(1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map({ok, CMC} | {error, CMD}, fun((CMC) -> CMG)) -> {ok, CMG} |
|
||||
{error, CMD}.
|
||||
map(Result, Fun) ->
|
||||
case Result of
|
||||
{ok, X} ->
|
||||
{ok, Fun(X)};
|
||||
|
||||
{error, E} ->
|
||||
{error, E}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 91).
|
||||
?DOC(
|
||||
" Updates a value held within the `Error` of a result by calling a given function\n"
|
||||
" on it.\n"
|
||||
"\n"
|
||||
" If the result is `Ok` rather than `Error` the function is not called and the\n"
|
||||
" result stays the same.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map_error(over: Error(1), with: fn(x) { x + 1 })\n"
|
||||
" // -> Error(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" map_error(over: Ok(1), with: fn(x) { x + 1 })\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map_error({ok, CMJ} | {error, CMK}, fun((CMK) -> CMN)) -> {ok, CMJ} |
|
||||
{error, CMN}.
|
||||
map_error(Result, Fun) ->
|
||||
case Result of
|
||||
{ok, X} ->
|
||||
{ok, X};
|
||||
|
||||
{error, Error} ->
|
||||
{error, Fun(Error)}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 120).
|
||||
?DOC(
|
||||
" Merges a nested `Result` into a single layer.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(Ok(Ok(1)))\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(Ok(Error(\"\")))\n"
|
||||
" // -> Error(\"\")\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" flatten(Error(Nil))\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec flatten({ok, {ok, CMQ} | {error, CMR}} | {error, CMR}) -> {ok, CMQ} |
|
||||
{error, CMR}.
|
||||
flatten(Result) ->
|
||||
case Result of
|
||||
{ok, X} ->
|
||||
X;
|
||||
|
||||
{error, Error} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 158).
|
||||
?DOC(
|
||||
" \"Updates\" an `Ok` result by passing its value to a function that yields a result,\n"
|
||||
" and returning the yielded result. (This may \"replace\" the `Ok` with an `Error`.)\n"
|
||||
"\n"
|
||||
" If the input is an `Error` rather than an `Ok`, the function is not called and\n"
|
||||
" the original `Error` is returned.\n"
|
||||
"\n"
|
||||
" This function is the equivalent of calling `map` followed by `flatten`, and\n"
|
||||
" it is useful for chaining together multiple functions that may fail.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" try(Ok(1), fn(x) { Ok(x + 1) })\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" try(Ok(1), fn(x) { Ok(#(\"a\", x)) })\n"
|
||||
" // -> Ok(#(\"a\", 1))\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" try(Ok(1), fn(_) { Error(\"Oh no\") })\n"
|
||||
" // -> Error(\"Oh no\")\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" try(Error(Nil), fn(x) { Ok(x + 1) })\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec 'try'({ok, CMY} | {error, CMZ}, fun((CMY) -> {ok, CNC} | {error, CMZ})) -> {ok,
|
||||
CNC} |
|
||||
{error, CMZ}.
|
||||
'try'(Result, Fun) ->
|
||||
case Result of
|
||||
{ok, X} ->
|
||||
Fun(X);
|
||||
|
||||
{error, E} ->
|
||||
{error, E}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 169).
|
||||
-spec then({ok, CNH} | {error, CNI}, fun((CNH) -> {ok, CNL} | {error, CNI})) -> {ok,
|
||||
CNL} |
|
||||
{error, CNI}.
|
||||
then(Result, Fun) ->
|
||||
'try'(Result, Fun).
|
||||
|
||||
-file("src/gleam/result.gleam", 191).
|
||||
?DOC(
|
||||
" Extracts the `Ok` value from a result, returning a default value if the result\n"
|
||||
" is an `Error`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap(Ok(1), 0)\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap(Error(\"\"), 0)\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec unwrap({ok, CNQ} | {error, any()}, CNQ) -> CNQ.
|
||||
unwrap(Result, Default) ->
|
||||
case Result of
|
||||
{ok, V} ->
|
||||
V;
|
||||
|
||||
{error, _} ->
|
||||
Default
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 213).
|
||||
?DOC(
|
||||
" Extracts the `Ok` value from a result, evaluating the default function if the result\n"
|
||||
" is an `Error`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_unwrap(Ok(1), fn() { 0 })\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_unwrap(Error(\"\"), fn() { 0 })\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_unwrap({ok, CNU} | {error, any()}, fun(() -> CNU)) -> CNU.
|
||||
lazy_unwrap(Result, Default) ->
|
||||
case Result of
|
||||
{ok, V} ->
|
||||
V;
|
||||
|
||||
{error, _} ->
|
||||
Default()
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 235).
|
||||
?DOC(
|
||||
" Extracts the `Error` value from a result, returning a default value if the result\n"
|
||||
" is an `Ok`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap_error(Error(1), 0)\n"
|
||||
" // -> 1\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" unwrap_error(Ok(\"\"), 0)\n"
|
||||
" // -> 0\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec unwrap_error({ok, any()} | {error, CNZ}, CNZ) -> CNZ.
|
||||
unwrap_error(Result, Default) ->
|
||||
case Result of
|
||||
{ok, _} ->
|
||||
Default;
|
||||
|
||||
{error, E} ->
|
||||
E
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 243).
|
||||
-spec unwrap_both({ok, COC} | {error, COC}) -> COC.
|
||||
unwrap_both(Result) ->
|
||||
case Result of
|
||||
{ok, A} ->
|
||||
A;
|
||||
|
||||
{error, A@1} ->
|
||||
A@1
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 274).
|
||||
?DOC(
|
||||
" Returns the first value if it is `Ok`, otherwise returns the second value.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Ok(1), Ok(2))\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Ok(1), Error(\"Error 2\"))\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Error(\"Error 1\"), Ok(2))\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" or(Error(\"Error 1\"), Error(\"Error 2\"))\n"
|
||||
" // -> Error(\"Error 2\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec 'or'({ok, COF} | {error, COG}, {ok, COF} | {error, COG}) -> {ok, COF} |
|
||||
{error, COG}.
|
||||
'or'(First, Second) ->
|
||||
case First of
|
||||
{ok, _} ->
|
||||
First;
|
||||
|
||||
{error, _} ->
|
||||
Second
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 307).
|
||||
?DOC(
|
||||
" Returns the first value if it is `Ok`, otherwise evaluates the given function for a fallback value.\n"
|
||||
"\n"
|
||||
" If you need access to the initial error value, use `result.try_recover`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Ok(1), fn() { Ok(2) })\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Ok(1), fn() { Error(\"Error 2\") })\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Error(\"Error 1\"), fn() { Ok(2) })\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" lazy_or(Error(\"Error 1\"), fn() { Error(\"Error 2\") })\n"
|
||||
" // -> Error(\"Error 2\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec lazy_or({ok, CON} | {error, COO}, fun(() -> {ok, CON} | {error, COO})) -> {ok,
|
||||
CON} |
|
||||
{error, COO}.
|
||||
lazy_or(First, Second) ->
|
||||
case First of
|
||||
{ok, _} ->
|
||||
First;
|
||||
|
||||
{error, _} ->
|
||||
Second()
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 333).
|
||||
?DOC(
|
||||
" Combines a list of results into a single result.\n"
|
||||
" If all elements in the list are `Ok` then returns an `Ok` holding the list of values.\n"
|
||||
" If any element is `Error` then returns the first error.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" all([Ok(1), Ok(2)])\n"
|
||||
" // -> Ok([1, 2])\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" all([Ok(1), Error(\"e\")])\n"
|
||||
" // -> Error(\"e\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec all(list({ok, COV} | {error, COW})) -> {ok, list(COV)} | {error, COW}.
|
||||
all(Results) ->
|
||||
gleam@list:try_map(Results, fun(Result) -> Result end).
|
||||
|
||||
-file("src/gleam/result.gleam", 353).
|
||||
-spec partition_loop(list({ok, CPK} | {error, CPL}), list(CPK), list(CPL)) -> {list(CPK),
|
||||
list(CPL)}.
|
||||
partition_loop(Results, Oks, Errors) ->
|
||||
case Results of
|
||||
[] ->
|
||||
{Oks, Errors};
|
||||
|
||||
[{ok, A} | Rest] ->
|
||||
partition_loop(Rest, [A | Oks], Errors);
|
||||
|
||||
[{error, E} | Rest@1] ->
|
||||
partition_loop(Rest@1, Oks, [E | Errors])
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 349).
|
||||
?DOC(
|
||||
" Given a list of results, returns a pair where the first element is a list\n"
|
||||
" of all the values inside `Ok` and the second element is a list with all the\n"
|
||||
" values inside `Error`. The values in both lists appear in reverse order with\n"
|
||||
" respect to their position in the original list of results.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" partition([Ok(1), Error(\"a\"), Error(\"b\"), Ok(2)])\n"
|
||||
" // -> #([2, 1], [\"b\", \"a\"])\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec partition(list({ok, CPD} | {error, CPE})) -> {list(CPD), list(CPE)}.
|
||||
partition(Results) ->
|
||||
partition_loop(Results, [], []).
|
||||
|
||||
-file("src/gleam/result.gleam", 375).
|
||||
?DOC(
|
||||
" Replace the value within a result\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" replace(Ok(1), Nil)\n"
|
||||
" // -> Ok(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" replace(Error(1), Nil)\n"
|
||||
" // -> Error(1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec replace({ok, any()} | {error, CPT}, CPW) -> {ok, CPW} | {error, CPT}.
|
||||
replace(Result, Value) ->
|
||||
case Result of
|
||||
{ok, _} ->
|
||||
{ok, Value};
|
||||
|
||||
{error, Error} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 396).
|
||||
?DOC(
|
||||
" Replace the error within a result\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" replace_error(Error(1), Nil)\n"
|
||||
" // -> Error(Nil)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" replace_error(Ok(1), Nil)\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec replace_error({ok, CPZ} | {error, any()}, CQD) -> {ok, CPZ} | {error, CQD}.
|
||||
replace_error(Result, Error) ->
|
||||
case Result of
|
||||
{ok, X} ->
|
||||
{ok, X};
|
||||
|
||||
{error, _} ->
|
||||
{error, Error}
|
||||
end.
|
||||
|
||||
-file("src/gleam/result.gleam", 412).
|
||||
?DOC(
|
||||
" Given a list of results, returns only the values inside `Ok`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" values([Ok(1), Error(\"a\"), Ok(3)])\n"
|
||||
" // -> [1, 3]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec values(list({ok, CQG} | {error, any()})) -> list(CQG).
|
||||
values(Results) ->
|
||||
gleam@list:filter_map(Results, fun(Result) -> Result end).
|
||||
|
||||
-file("src/gleam/result.gleam", 445).
|
||||
?DOC(
|
||||
" Updates a value held within the `Error` of a result by calling a given function\n"
|
||||
" on it, where the given function also returns a result. The two results are\n"
|
||||
" then merged together into one result.\n"
|
||||
"\n"
|
||||
" If the result is an `Ok` rather than `Error` the function is not called and the\n"
|
||||
" result stays the same.\n"
|
||||
"\n"
|
||||
" This function is useful for chaining together computations that may fail\n"
|
||||
" and trying to recover from possible errors.\n"
|
||||
"\n"
|
||||
" If you do not need access to the initial error value, use `result.lazy_or`.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" Ok(1) |> try_recover(with: fn(_) { Error(\"failed to recover\") })\n"
|
||||
" // -> Ok(1)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" Error(1) |> try_recover(with: fn(error) { Ok(error + 1) })\n"
|
||||
" // -> Ok(2)\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" Error(1) |> try_recover(with: fn(error) { Error(\"failed to recover\") })\n"
|
||||
" // -> Error(\"failed to recover\")\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec try_recover(
|
||||
{ok, CQM} | {error, CQN},
|
||||
fun((CQN) -> {ok, CQM} | {error, CQQ})
|
||||
) -> {ok, CQM} | {error, CQQ}.
|
||||
try_recover(Result, Fun) ->
|
||||
case Result of
|
||||
{ok, Value} ->
|
||||
{ok, Value};
|
||||
|
||||
{error, Error} ->
|
||||
Fun(Error)
|
||||
end.
|
||||
429
build/dev/javascript/gleam_stdlib/gleam@set.erl
Normal file
429
build/dev/javascript/gleam_stdlib/gleam@set.erl
Normal file
|
|
@ -0,0 +1,429 @@
|
|||
-module(gleam@set).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/set.gleam").
|
||||
-export([new/0, size/1, is_empty/1, contains/2, delete/2, to_list/1, fold/3, filter/2, drop/2, take/2, intersection/2, difference/2, is_subset/2, is_disjoint/2, each/2, insert/2, from_list/1, map/2, union/2, symmetric_difference/2]).
|
||||
-export_type([set/1]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-opaque set(CVL) :: {set, gleam@dict:dict(CVL, list(nil))}.
|
||||
|
||||
-file("src/gleam/set.gleam", 32).
|
||||
?DOC(" Creates a new empty set.\n").
|
||||
-spec new() -> set(any()).
|
||||
new() ->
|
||||
{set, maps:new()}.
|
||||
|
||||
-file("src/gleam/set.gleam", 50).
|
||||
?DOC(
|
||||
" Gets the number of members in a set.\n"
|
||||
"\n"
|
||||
" This function runs in constant time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new()\n"
|
||||
" |> insert(1)\n"
|
||||
" |> insert(2)\n"
|
||||
" |> size\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec size(set(any())) -> integer().
|
||||
size(Set) ->
|
||||
maps:size(erlang:element(2, Set)).
|
||||
|
||||
-file("src/gleam/set.gleam", 68).
|
||||
?DOC(
|
||||
" Determines whether or not the set is empty.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> is_empty\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(1) |> is_empty\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_empty(set(any())) -> boolean().
|
||||
is_empty(Set) ->
|
||||
Set =:= new().
|
||||
|
||||
-file("src/gleam/set.gleam", 110).
|
||||
?DOC(
|
||||
" Checks whether a set contains a given member.\n"
|
||||
"\n"
|
||||
" This function runs in logarithmic time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new()\n"
|
||||
" |> insert(2)\n"
|
||||
" |> contains(2)\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new()\n"
|
||||
" |> insert(2)\n"
|
||||
" |> contains(1)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec contains(set(CVW), CVW) -> boolean().
|
||||
contains(Set, Member) ->
|
||||
_pipe = erlang:element(2, Set),
|
||||
_pipe@1 = gleam_stdlib:map_get(_pipe, Member),
|
||||
gleam@result:is_ok(_pipe@1).
|
||||
|
||||
-file("src/gleam/set.gleam", 131).
|
||||
?DOC(
|
||||
" Removes a member from a set. If the set does not contain the member then\n"
|
||||
" the set is returned unchanged.\n"
|
||||
"\n"
|
||||
" This function runs in logarithmic time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new()\n"
|
||||
" |> insert(2)\n"
|
||||
" |> delete(2)\n"
|
||||
" |> contains(1)\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec delete(set(CVY), CVY) -> set(CVY).
|
||||
delete(Set, Member) ->
|
||||
{set, gleam@dict:delete(erlang:element(2, Set), Member)}.
|
||||
|
||||
-file("src/gleam/set.gleam", 149).
|
||||
?DOC(
|
||||
" Converts the set into a list of the contained members.\n"
|
||||
"\n"
|
||||
" The list has no specific ordering, any unintentional ordering may change in\n"
|
||||
" future versions of Gleam or Erlang.\n"
|
||||
"\n"
|
||||
" This function runs in linear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new() |> insert(2) |> to_list\n"
|
||||
" // -> [2]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec to_list(set(CWB)) -> list(CWB).
|
||||
to_list(Set) ->
|
||||
maps:keys(erlang:element(2, Set)).
|
||||
|
||||
-file("src/gleam/set.gleam", 190).
|
||||
?DOC(
|
||||
" Combines all entries into a single value by calling a given function on each\n"
|
||||
" one.\n"
|
||||
"\n"
|
||||
" Sets are not ordered so the values are not returned in any specific order.\n"
|
||||
" Do not write code that relies on the order entries are used by this\n"
|
||||
" function as it may change in later versions of Gleam or Erlang.\n"
|
||||
"\n"
|
||||
" # Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([1, 3, 9])\n"
|
||||
" |> fold(0, fn(accumulator, member) { accumulator + member })\n"
|
||||
" // -> 13\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec fold(set(CWH), CWJ, fun((CWJ, CWH) -> CWJ)) -> CWJ.
|
||||
fold(Set, Initial, Reducer) ->
|
||||
gleam@dict:fold(
|
||||
erlang:element(2, Set),
|
||||
Initial,
|
||||
fun(A, K, _) -> Reducer(A, K) end
|
||||
).
|
||||
|
||||
-file("src/gleam/set.gleam", 214).
|
||||
?DOC(
|
||||
" Creates a new set from an existing set, minus any members that a given\n"
|
||||
" function returns `False` for.\n"
|
||||
"\n"
|
||||
" This function runs in loglinear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
"\n"
|
||||
" from_list([1, 4, 6, 3, 675, 44, 67])\n"
|
||||
" |> filter(keeping: int.is_even)\n"
|
||||
" |> to_list\n"
|
||||
" // -> [4, 6, 44]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec filter(set(CWK), fun((CWK) -> boolean())) -> set(CWK).
|
||||
filter(Set, Predicate) ->
|
||||
{set,
|
||||
gleam@dict:filter(erlang:element(2, Set), fun(M, _) -> Predicate(M) end)}.
|
||||
|
||||
-file("src/gleam/set.gleam", 249).
|
||||
?DOC(
|
||||
" Creates a new set from a given set with all the same entries except any\n"
|
||||
" entry found on the given list.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([1, 2, 3, 4])\n"
|
||||
" |> drop([1, 3])\n"
|
||||
" |> to_list\n"
|
||||
" // -> [2, 4]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec drop(set(CWR), list(CWR)) -> set(CWR).
|
||||
drop(Set, Disallowed) ->
|
||||
gleam@list:fold(Disallowed, Set, fun delete/2).
|
||||
|
||||
-file("src/gleam/set.gleam", 267).
|
||||
?DOC(
|
||||
" Creates a new set from a given set, only including any members which are in\n"
|
||||
" a given list.\n"
|
||||
"\n"
|
||||
" This function runs in loglinear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([1, 2, 3])\n"
|
||||
" |> take([1, 3, 5])\n"
|
||||
" |> to_list\n"
|
||||
" // -> [1, 3]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec take(set(CWV), list(CWV)) -> set(CWV).
|
||||
take(Set, Desired) ->
|
||||
{set, gleam@dict:take(erlang:element(2, Set), Desired)}.
|
||||
|
||||
-file("src/gleam/set.gleam", 287).
|
||||
-spec order(set(CXD), set(CXD)) -> {set(CXD), set(CXD)}.
|
||||
order(First, Second) ->
|
||||
case maps:size(erlang:element(2, First)) > maps:size(
|
||||
erlang:element(2, Second)
|
||||
) of
|
||||
true ->
|
||||
{First, Second};
|
||||
|
||||
false ->
|
||||
{Second, First}
|
||||
end.
|
||||
|
||||
-file("src/gleam/set.gleam", 305).
|
||||
?DOC(
|
||||
" Creates a new set that contains members that are present in both given sets.\n"
|
||||
"\n"
|
||||
" This function runs in loglinear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" intersection(from_list([1, 2]), from_list([2, 3])) |> to_list\n"
|
||||
" // -> [2]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec intersection(set(CXI), set(CXI)) -> set(CXI).
|
||||
intersection(First, Second) ->
|
||||
{Larger, Smaller} = order(First, Second),
|
||||
take(Larger, to_list(Smaller)).
|
||||
|
||||
-file("src/gleam/set.gleam", 323).
|
||||
?DOC(
|
||||
" Creates a new set that contains members that are present in the first set\n"
|
||||
" but not the second.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" difference(from_list([1, 2]), from_list([2, 3, 4])) |> to_list\n"
|
||||
" // -> [1]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec difference(set(CXM), set(CXM)) -> set(CXM).
|
||||
difference(First, Second) ->
|
||||
drop(First, to_list(Second)).
|
||||
|
||||
-file("src/gleam/set.gleam", 344).
|
||||
?DOC(
|
||||
" Determines if a set is fully contained by another.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_subset(from_list([1]), from_list([1, 2]))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_subset(from_list([1, 2, 3]), from_list([3, 4, 5]))\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_subset(set(CXQ), set(CXQ)) -> boolean().
|
||||
is_subset(First, Second) ->
|
||||
intersection(First, Second) =:= First.
|
||||
|
||||
-file("src/gleam/set.gleam", 362).
|
||||
?DOC(
|
||||
" Determines if two sets contain no common members\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_disjoint(from_list([1, 2, 3]), from_list([4, 5, 6]))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_disjoint(from_list([1, 2, 3]), from_list([3, 4, 5]))\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_disjoint(set(CXT), set(CXT)) -> boolean().
|
||||
is_disjoint(First, Second) ->
|
||||
intersection(First, Second) =:= new().
|
||||
|
||||
-file("src/gleam/set.gleam", 402).
|
||||
?DOC(
|
||||
" Calls a function for each member in a set, discarding the return\n"
|
||||
" value.\n"
|
||||
"\n"
|
||||
" Useful for producing a side effect for every item of a set.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" let set = from_list([\"apple\", \"banana\", \"cherry\"])\n"
|
||||
"\n"
|
||||
" each(set, io.println)\n"
|
||||
" // -> Nil\n"
|
||||
" // apple\n"
|
||||
" // banana\n"
|
||||
" // cherry\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" The order of elements in the iteration is an implementation detail that\n"
|
||||
" should not be relied upon.\n"
|
||||
).
|
||||
-spec each(set(CYA), fun((CYA) -> any())) -> nil.
|
||||
each(Set, Fun) ->
|
||||
fold(
|
||||
Set,
|
||||
nil,
|
||||
fun(Nil, Member) ->
|
||||
Fun(Member),
|
||||
Nil
|
||||
end
|
||||
).
|
||||
|
||||
-file("src/gleam/set.gleam", 86).
|
||||
?DOC(
|
||||
" Inserts an member into the set.\n"
|
||||
"\n"
|
||||
" This function runs in logarithmic time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" new()\n"
|
||||
" |> insert(1)\n"
|
||||
" |> insert(2)\n"
|
||||
" |> size\n"
|
||||
" // -> 2\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec insert(set(CVT), CVT) -> set(CVT).
|
||||
insert(Set, Member) ->
|
||||
{set, gleam@dict:insert(erlang:element(2, Set), Member, [])}.
|
||||
|
||||
-file("src/gleam/set.gleam", 167).
|
||||
?DOC(
|
||||
" Creates a new set of the members in a given list.\n"
|
||||
"\n"
|
||||
" This function runs in loglinear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" import gleam/int\n"
|
||||
" import gleam/list\n"
|
||||
"\n"
|
||||
" [1, 1, 2, 4, 3, 2] |> from_list |> to_list |> list.sort(by: int.compare)\n"
|
||||
" // -> [1, 2, 3, 4]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec from_list(list(CWE)) -> set(CWE).
|
||||
from_list(Members) ->
|
||||
Dict = gleam@list:fold(
|
||||
Members,
|
||||
maps:new(),
|
||||
fun(M, K) -> gleam@dict:insert(M, K, []) end
|
||||
),
|
||||
{set, Dict}.
|
||||
|
||||
-file("src/gleam/set.gleam", 232).
|
||||
?DOC(
|
||||
" Creates a new set from a given set with the result of applying the given\n"
|
||||
" function to each member.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_list([1, 2, 3, 4])\n"
|
||||
" |> map(with: fn(x) { x * 2 })\n"
|
||||
" |> to_list\n"
|
||||
" // -> [2, 4, 6, 8]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec map(set(CWN), fun((CWN) -> CWP)) -> set(CWP).
|
||||
map(Set, Fun) ->
|
||||
fold(Set, new(), fun(Acc, Member) -> insert(Acc, Fun(Member)) end).
|
||||
|
||||
-file("src/gleam/set.gleam", 282).
|
||||
?DOC(
|
||||
" Creates a new set that contains all members of both given sets.\n"
|
||||
"\n"
|
||||
" This function runs in loglinear time.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" union(from_list([1, 2]), from_list([2, 3])) |> to_list\n"
|
||||
" // -> [1, 2, 3]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec union(set(CWZ), set(CWZ)) -> set(CWZ).
|
||||
union(First, Second) ->
|
||||
{Larger, Smaller} = order(First, Second),
|
||||
fold(Smaller, Larger, fun insert/2).
|
||||
|
||||
-file("src/gleam/set.gleam", 374).
|
||||
?DOC(
|
||||
" Creates a new set that contains members that are present in either set, but\n"
|
||||
" not both.\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" symmetric_difference(from_list([1, 2, 3]), from_list([3, 4])) |> to_list\n"
|
||||
" // -> [1, 2, 4]\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec symmetric_difference(set(CXW), set(CXW)) -> set(CXW).
|
||||
symmetric_difference(First, Second) ->
|
||||
difference(union(First, Second), intersection(First, Second)).
|
||||
1012
build/dev/javascript/gleam_stdlib/gleam@string.erl
Normal file
1012
build/dev/javascript/gleam_stdlib/gleam@string.erl
Normal file
File diff suppressed because it is too large
Load diff
207
build/dev/javascript/gleam_stdlib/gleam@string_tree.erl
Normal file
207
build/dev/javascript/gleam_stdlib/gleam@string_tree.erl
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
-module(gleam@string_tree).
|
||||
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
|
||||
-define(FILEPATH, "src/gleam/string_tree.gleam").
|
||||
-export([append_tree/2, prepend_tree/2, from_strings/1, new/0, concat/1, from_string/1, prepend/2, append/2, to_string/1, byte_size/1, join/2, lowercase/1, uppercase/1, reverse/1, split/2, replace/3, is_equal/2, is_empty/1]).
|
||||
-export_type([string_tree/0, direction/0]).
|
||||
|
||||
-if(?OTP_RELEASE >= 27).
|
||||
-define(MODULEDOC(Str), -moduledoc(Str)).
|
||||
-define(DOC(Str), -doc(Str)).
|
||||
-else.
|
||||
-define(MODULEDOC(Str), -compile([])).
|
||||
-define(DOC(Str), -compile([])).
|
||||
-endif.
|
||||
|
||||
-type string_tree() :: any().
|
||||
|
||||
-type direction() :: all.
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 61).
|
||||
?DOC(
|
||||
" Appends some `StringTree` onto the end of another.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec append_tree(string_tree(), string_tree()) -> string_tree().
|
||||
append_tree(Tree, Suffix) ->
|
||||
gleam_stdlib:iodata_append(Tree, Suffix).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 48).
|
||||
?DOC(
|
||||
" Prepends some `StringTree` onto the start of another.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec prepend_tree(string_tree(), string_tree()) -> string_tree().
|
||||
prepend_tree(Tree, Prefix) ->
|
||||
gleam_stdlib:iodata_append(Prefix, Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 69).
|
||||
?DOC(
|
||||
" Converts a list of strings into a `StringTree`.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec from_strings(list(binary())) -> string_tree().
|
||||
from_strings(Strings) ->
|
||||
gleam_stdlib:identity(Strings).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 24).
|
||||
?DOC(
|
||||
" Create an empty `StringTree`. Useful as the start of a pipe chaining many\n"
|
||||
" trees together.\n"
|
||||
).
|
||||
-spec new() -> string_tree().
|
||||
new() ->
|
||||
gleam_stdlib:identity([]).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 77).
|
||||
?DOC(
|
||||
" Joins a list of trees into a single tree.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec concat(list(string_tree())) -> string_tree().
|
||||
concat(Trees) ->
|
||||
gleam_stdlib:identity(Trees).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 85).
|
||||
?DOC(
|
||||
" Converts a string into a `StringTree`.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec from_string(binary()) -> string_tree().
|
||||
from_string(String) ->
|
||||
gleam_stdlib:identity(String).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 32).
|
||||
?DOC(
|
||||
" Prepends a `String` onto the start of some `StringTree`.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec prepend(string_tree(), binary()) -> string_tree().
|
||||
prepend(Tree, Prefix) ->
|
||||
gleam_stdlib:iodata_append(gleam_stdlib:identity(Prefix), Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 40).
|
||||
?DOC(
|
||||
" Appends a `String` onto the end of some `StringTree`.\n"
|
||||
"\n"
|
||||
" Runs in constant time.\n"
|
||||
).
|
||||
-spec append(string_tree(), binary()) -> string_tree().
|
||||
append(Tree, Second) ->
|
||||
gleam_stdlib:iodata_append(Tree, gleam_stdlib:identity(Second)).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 94).
|
||||
?DOC(
|
||||
" Turns a `StringTree` into a `String`\n"
|
||||
"\n"
|
||||
" This function is implemented natively by the virtual machine and is highly\n"
|
||||
" optimised.\n"
|
||||
).
|
||||
-spec to_string(string_tree()) -> binary().
|
||||
to_string(Tree) ->
|
||||
unicode:characters_to_binary(Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 100).
|
||||
?DOC(" Returns the size of the `StringTree` in bytes.\n").
|
||||
-spec byte_size(string_tree()) -> integer().
|
||||
byte_size(Tree) ->
|
||||
erlang:iolist_size(Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 104).
|
||||
?DOC(" Joins the given trees into a new tree separated with the given string.\n").
|
||||
-spec join(list(string_tree()), binary()) -> string_tree().
|
||||
join(Trees, Sep) ->
|
||||
_pipe = Trees,
|
||||
_pipe@1 = gleam@list:intersperse(_pipe, gleam_stdlib:identity(Sep)),
|
||||
gleam_stdlib:identity(_pipe@1).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 115).
|
||||
?DOC(
|
||||
" Converts a `StringTree` to a new one where the contents have been\n"
|
||||
" lowercased.\n"
|
||||
).
|
||||
-spec lowercase(string_tree()) -> string_tree().
|
||||
lowercase(Tree) ->
|
||||
string:lowercase(Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 122).
|
||||
?DOC(
|
||||
" Converts a `StringTree` to a new one where the contents have been\n"
|
||||
" uppercased.\n"
|
||||
).
|
||||
-spec uppercase(string_tree()) -> string_tree().
|
||||
uppercase(Tree) ->
|
||||
string:uppercase(Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 127).
|
||||
?DOC(" Converts a `StringTree` to a new one with the contents reversed.\n").
|
||||
-spec reverse(string_tree()) -> string_tree().
|
||||
reverse(Tree) ->
|
||||
string:reverse(Tree).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 145).
|
||||
?DOC(" Splits a `StringTree` on a given pattern into a list of trees.\n").
|
||||
-spec split(string_tree(), binary()) -> list(string_tree()).
|
||||
split(Tree, Pattern) ->
|
||||
string:split(Tree, Pattern, all).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 156).
|
||||
?DOC(" Replaces all instances of a pattern with a given string substitute.\n").
|
||||
-spec replace(string_tree(), binary(), binary()) -> string_tree().
|
||||
replace(Tree, Pattern, Substitute) ->
|
||||
gleam_stdlib:string_replace(Tree, Pattern, Substitute).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 182).
|
||||
?DOC(
|
||||
" Compares two string trees to determine if they have the same textual\n"
|
||||
" content.\n"
|
||||
"\n"
|
||||
" Comparing two string trees using the `==` operator may return `False` even\n"
|
||||
" if they have the same content as they may have been build in different ways,\n"
|
||||
" so using this function is often preferred.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_strings([\"a\", \"b\"]) == from_string(\"ab\")\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" is_equal(from_strings([\"a\", \"b\"]), from_string(\"ab\"))\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_equal(string_tree(), string_tree()) -> boolean().
|
||||
is_equal(A, B) ->
|
||||
string:equal(A, B).
|
||||
|
||||
-file("src/gleam/string_tree.gleam", 206).
|
||||
?DOC(
|
||||
" Inspects a `StringTree` to determine if it is equivalent to an empty string.\n"
|
||||
"\n"
|
||||
" ## Examples\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_string(\"ok\") |> is_empty\n"
|
||||
" // -> False\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_string(\"\") |> is_empty\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
"\n"
|
||||
" ```gleam\n"
|
||||
" from_strings([]) |> is_empty\n"
|
||||
" // -> True\n"
|
||||
" ```\n"
|
||||
).
|
||||
-spec is_empty(string_tree()) -> boolean().
|
||||
is_empty(Tree) ->
|
||||
string:is_empty(Tree).
|
||||
1044
build/dev/javascript/gleam_stdlib/gleam@uri.erl
Normal file
1044
build/dev/javascript/gleam_stdlib/gleam@uri.erl
Normal file
File diff suppressed because it is too large
Load diff
534
build/dev/javascript/gleam_stdlib/gleam_stdlib.erl
Normal file
534
build/dev/javascript/gleam_stdlib/gleam_stdlib.erl
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
-module(gleam_stdlib).
|
||||
|
||||
-export([
|
||||
map_get/2, iodata_append/2, identity/1, parse_int/1, parse_float/1,
|
||||
less_than/2, string_pop_grapheme/1, string_pop_codeunit/1,
|
||||
string_starts_with/2, wrap_list/1, string_ends_with/2, string_pad/4,
|
||||
uri_parse/1, bit_array_slice/3, percent_encode/1, percent_decode/1,
|
||||
base64_decode/1, parse_query/1, bit_array_concat/1,
|
||||
base64_encode/2, tuple_get/2, classify_dynamic/1, print/1,
|
||||
println/1, print_error/1, println_error/1, inspect/1, float_to_string/1,
|
||||
int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2,
|
||||
crop_string/2, base16_encode/1, base16_decode/1, string_replace/3, slice/3,
|
||||
bit_array_to_int_and_size/1, bit_array_pad_to_bytes/1, index/2, list/5,
|
||||
dict/1, int/1, float/1, bit_array/1, is_null/1
|
||||
]).
|
||||
|
||||
%% Taken from OTP's uri_string module
|
||||
-define(DEC2HEX(X),
|
||||
if ((X) >= 0) andalso ((X) =< 9) -> (X) + $0;
|
||||
((X) >= 10) andalso ((X) =< 15) -> (X) + $A - 10
|
||||
end).
|
||||
|
||||
%% Taken from OTP's uri_string module
|
||||
-define(HEX2DEC(X),
|
||||
if ((X) >= $0) andalso ((X) =< $9) -> (X) - $0;
|
||||
((X) >= $A) andalso ((X) =< $F) -> (X) - $A + 10;
|
||||
((X) >= $a) andalso ((X) =< $f) -> (X) - $a + 10
|
||||
end).
|
||||
|
||||
-define(is_lowercase_char(X),
|
||||
(X > 96 andalso X < 123)).
|
||||
-define(is_underscore_char(X),
|
||||
(X == 95)).
|
||||
-define(is_digit_char(X),
|
||||
(X > 47 andalso X < 58)).
|
||||
-define(is_ascii_character(X),
|
||||
(erlang:is_integer(X) andalso X >= 32 andalso X =< 126)).
|
||||
|
||||
uppercase(X) -> X - 32.
|
||||
|
||||
map_get(Map, Key) ->
|
||||
case maps:find(Key, Map) of
|
||||
error -> {error, nil};
|
||||
OkFound -> OkFound
|
||||
end.
|
||||
|
||||
iodata_append(Iodata, String) -> [Iodata, String].
|
||||
|
||||
identity(X) -> X.
|
||||
|
||||
classify_dynamic(nil) -> <<"Nil">>;
|
||||
classify_dynamic(null) -> <<"Nil">>;
|
||||
classify_dynamic(undefined) -> <<"Nil">>;
|
||||
classify_dynamic(X) when is_boolean(X) -> <<"Bool">>;
|
||||
classify_dynamic(X) when is_atom(X) -> <<"Atom">>;
|
||||
classify_dynamic(X) when is_binary(X) -> <<"String">>;
|
||||
classify_dynamic(X) when is_bitstring(X) -> <<"BitArray">>;
|
||||
classify_dynamic(X) when is_integer(X) -> <<"Int">>;
|
||||
classify_dynamic(X) when is_float(X) -> <<"Float">>;
|
||||
classify_dynamic(X) when is_list(X) -> <<"List">>;
|
||||
classify_dynamic(X) when is_map(X) -> <<"Dict">>;
|
||||
classify_dynamic(X) when is_tuple(X) -> <<"Array">>;
|
||||
classify_dynamic(X) when is_reference(X) -> <<"Reference">>;
|
||||
classify_dynamic(X) when is_pid(X) -> <<"Pid">>;
|
||||
classify_dynamic(X) when is_port(X) -> <<"Port">>;
|
||||
classify_dynamic(X) when
|
||||
is_function(X, 0) orelse is_function(X, 1) orelse is_function(X, 2) orelse
|
||||
is_function(X, 3) orelse is_function(X, 4) orelse is_function(X, 5) orelse
|
||||
is_function(X, 6) orelse is_function(X, 7) orelse is_function(X, 8) orelse
|
||||
is_function(X, 9) orelse is_function(X, 10) orelse is_function(X, 11) orelse
|
||||
is_function(X, 12) -> <<"Function">>;
|
||||
classify_dynamic(_) -> <<"Unknown">>.
|
||||
|
||||
tuple_get(_tup, Index) when Index < 0 -> {error, nil};
|
||||
tuple_get(Data, Index) when Index >= tuple_size(Data) -> {error, nil};
|
||||
tuple_get(Data, Index) -> {ok, element(Index + 1, Data)}.
|
||||
|
||||
int_from_base_string(String, Base) ->
|
||||
case catch binary_to_integer(String, Base) of
|
||||
Int when is_integer(Int) -> {ok, Int};
|
||||
_ -> {error, nil}
|
||||
end.
|
||||
|
||||
parse_int(String) ->
|
||||
case catch binary_to_integer(String) of
|
||||
Int when is_integer(Int) -> {ok, Int};
|
||||
_ -> {error, nil}
|
||||
end.
|
||||
|
||||
parse_float(String) ->
|
||||
case catch binary_to_float(String) of
|
||||
Float when is_float(Float) -> {ok, Float};
|
||||
_ -> {error, nil}
|
||||
end.
|
||||
|
||||
less_than(Lhs, Rhs) ->
|
||||
Lhs < Rhs.
|
||||
|
||||
string_starts_with(_, <<>>) -> true;
|
||||
string_starts_with(String, Prefix) when byte_size(Prefix) > byte_size(String) -> false;
|
||||
string_starts_with(String, Prefix) ->
|
||||
PrefixSize = byte_size(Prefix),
|
||||
Prefix == binary_part(String, 0, PrefixSize).
|
||||
|
||||
string_ends_with(_, <<>>) -> true;
|
||||
string_ends_with(String, Suffix) when byte_size(Suffix) > byte_size(String) -> false;
|
||||
string_ends_with(String, Suffix) ->
|
||||
SuffixSize = byte_size(Suffix),
|
||||
Suffix == binary_part(String, byte_size(String) - SuffixSize, SuffixSize).
|
||||
|
||||
string_pad(String, Length, Dir, PadString) ->
|
||||
Chars = string:pad(String, Length, Dir, binary_to_list(PadString)),
|
||||
case unicode:characters_to_binary(Chars) of
|
||||
Bin when is_binary(Bin) -> Bin;
|
||||
Error -> erlang:error({gleam_error, {string_invalid_utf8, Error}})
|
||||
end.
|
||||
|
||||
string_pop_grapheme(String) ->
|
||||
case string:next_grapheme(String) of
|
||||
[ Next | Rest ] when is_binary(Rest) ->
|
||||
{ok, {unicode:characters_to_binary([Next]), Rest}};
|
||||
|
||||
[ Next | Rest ] ->
|
||||
{ok, {unicode:characters_to_binary([Next]), unicode:characters_to_binary(Rest)}};
|
||||
|
||||
_ -> {error, nil}
|
||||
end.
|
||||
|
||||
string_pop_codeunit(<<Cp/integer, Rest/binary>>) -> {Cp, Rest};
|
||||
string_pop_codeunit(Binary) -> {0, Binary}.
|
||||
|
||||
bit_array_pad_to_bytes(Bin) ->
|
||||
case erlang:bit_size(Bin) rem 8 of
|
||||
0 -> Bin;
|
||||
TrailingBits ->
|
||||
PaddingBits = 8 - TrailingBits,
|
||||
<<Bin/bits, 0:PaddingBits>>
|
||||
end.
|
||||
|
||||
bit_array_concat(BitArrays) ->
|
||||
list_to_bitstring(BitArrays).
|
||||
|
||||
-if(?OTP_RELEASE >= 26).
|
||||
base64_encode(Bin, Padding) ->
|
||||
PaddedBin = bit_array_pad_to_bytes(Bin),
|
||||
base64:encode(PaddedBin, #{padding => Padding}).
|
||||
-else.
|
||||
base64_encode(_Bin, _Padding) ->
|
||||
erlang:error(<<"Erlang OTP/26 or higher is required to use base64:encode">>).
|
||||
-endif.
|
||||
|
||||
bit_array_slice(Bin, Pos, Len) ->
|
||||
try {ok, binary:part(Bin, Pos, Len)}
|
||||
catch error:badarg -> {error, nil}
|
||||
end.
|
||||
|
||||
base64_decode(S) ->
|
||||
try {ok, base64:decode(S)}
|
||||
catch error:_ -> {error, nil}
|
||||
end.
|
||||
|
||||
wrap_list(X) when is_list(X) -> X;
|
||||
wrap_list(X) -> [X].
|
||||
|
||||
parse_query(Query) ->
|
||||
case uri_string:dissect_query(Query) of
|
||||
{error, _, _} -> {error, nil};
|
||||
Pairs ->
|
||||
Pairs1 = lists:map(fun
|
||||
({K, true}) -> {K, <<"">>};
|
||||
(Pair) -> Pair
|
||||
end, Pairs),
|
||||
{ok, Pairs1}
|
||||
end.
|
||||
|
||||
percent_encode(B) -> percent_encode(B, <<>>).
|
||||
percent_encode(<<>>, Acc) ->
|
||||
Acc;
|
||||
percent_encode(<<H,T/binary>>, Acc) ->
|
||||
case percent_ok(H) of
|
||||
true ->
|
||||
percent_encode(T, <<Acc/binary,H>>);
|
||||
false ->
|
||||
<<A:4,B:4>> = <<H>>,
|
||||
percent_encode(T, <<Acc/binary,$%,(?DEC2HEX(A)),(?DEC2HEX(B))>>)
|
||||
end.
|
||||
|
||||
percent_decode(Cs) -> percent_decode(Cs, <<>>).
|
||||
percent_decode(<<$%, C0, C1, Cs/binary>>, Acc) ->
|
||||
case is_hex_digit(C0) andalso is_hex_digit(C1) of
|
||||
true ->
|
||||
B = ?HEX2DEC(C0)*16+?HEX2DEC(C1),
|
||||
percent_decode(Cs, <<Acc/binary, B>>);
|
||||
false ->
|
||||
{error, nil}
|
||||
end;
|
||||
percent_decode(<<C,Cs/binary>>, Acc) ->
|
||||
percent_decode(Cs, <<Acc/binary, C>>);
|
||||
percent_decode(<<>>, Acc) ->
|
||||
check_utf8(Acc).
|
||||
|
||||
percent_ok($!) -> true;
|
||||
percent_ok($$) -> true;
|
||||
percent_ok($') -> true;
|
||||
percent_ok($() -> true;
|
||||
percent_ok($)) -> true;
|
||||
percent_ok($*) -> true;
|
||||
percent_ok($+) -> true;
|
||||
percent_ok($-) -> true;
|
||||
percent_ok($.) -> true;
|
||||
percent_ok($_) -> true;
|
||||
percent_ok($~) -> true;
|
||||
percent_ok(C) when $0 =< C, C =< $9 -> true;
|
||||
percent_ok(C) when $A =< C, C =< $Z -> true;
|
||||
percent_ok(C) when $a =< C, C =< $z -> true;
|
||||
percent_ok(_) -> false.
|
||||
|
||||
is_hex_digit(C) ->
|
||||
($0 =< C andalso C =< $9) orelse ($a =< C andalso C =< $f) orelse ($A =< C andalso C =< $F).
|
||||
|
||||
check_utf8(Cs) ->
|
||||
case unicode:characters_to_list(Cs) of
|
||||
{incomplete, _, _} -> {error, nil};
|
||||
{error, _, _} -> {error, nil};
|
||||
_ -> {ok, Cs}
|
||||
end.
|
||||
|
||||
uri_parse(String) ->
|
||||
case uri_string:parse(String) of
|
||||
{error, _, _} -> {error, nil};
|
||||
Uri ->
|
||||
Port =
|
||||
try maps:get(port, Uri) of
|
||||
undefined -> none;
|
||||
Value -> {some, Value}
|
||||
catch _:_ -> none
|
||||
end,
|
||||
{ok, {uri,
|
||||
maps_get_optional(Uri, scheme),
|
||||
maps_get_optional(Uri, userinfo),
|
||||
maps_get_optional(Uri, host),
|
||||
Port,
|
||||
maps_get_or(Uri, path, <<>>),
|
||||
maps_get_optional(Uri, query),
|
||||
maps_get_optional(Uri, fragment)
|
||||
}}
|
||||
end.
|
||||
|
||||
maps_get_optional(Map, Key) ->
|
||||
try {some, maps:get(Key, Map)}
|
||||
catch _:_ -> none
|
||||
end.
|
||||
|
||||
maps_get_or(Map, Key, Default) ->
|
||||
try maps:get(Key, Map)
|
||||
catch _:_ -> Default
|
||||
end.
|
||||
|
||||
print(String) ->
|
||||
io:put_chars(String),
|
||||
nil.
|
||||
|
||||
println(String) ->
|
||||
io:put_chars([String, $\n]),
|
||||
nil.
|
||||
|
||||
print_error(String) ->
|
||||
io:put_chars(standard_error, String),
|
||||
nil.
|
||||
|
||||
println_error(String) ->
|
||||
io:put_chars(standard_error, [String, $\n]),
|
||||
nil.
|
||||
|
||||
inspect(true) ->
|
||||
"True";
|
||||
inspect(false) ->
|
||||
"False";
|
||||
inspect(nil) ->
|
||||
"Nil";
|
||||
inspect(Data) when is_map(Data) ->
|
||||
Fields = [
|
||||
[<<"#(">>, inspect(Key), <<", ">>, inspect(Value), <<")">>]
|
||||
|| {Key, Value} <- maps:to_list(Data)
|
||||
],
|
||||
["dict.from_list([", lists:join(", ", Fields), "])"];
|
||||
inspect(Atom) when is_atom(Atom) ->
|
||||
erlang:element(2, inspect_atom(Atom));
|
||||
inspect(Any) when is_integer(Any) ->
|
||||
erlang:integer_to_list(Any);
|
||||
inspect(Any) when is_float(Any) ->
|
||||
io_lib_format:fwrite_g(Any);
|
||||
inspect(Binary) when is_binary(Binary) ->
|
||||
case inspect_maybe_utf8_string(Binary, <<>>) of
|
||||
{ok, InspectedUtf8String} -> InspectedUtf8String;
|
||||
{error, not_a_utf8_string} ->
|
||||
Segments = [erlang:integer_to_list(X) || <<X>> <= Binary],
|
||||
["<<", lists:join(", ", Segments), ">>"]
|
||||
end;
|
||||
inspect(Bits) when is_bitstring(Bits) ->
|
||||
inspect_bit_array(Bits);
|
||||
inspect(List) when is_list(List) ->
|
||||
case inspect_list(List, true) of
|
||||
{charlist, _} -> ["charlist.from_string(\"", list_to_binary(List), "\")"];
|
||||
{proper, Elements} -> ["[", Elements, "]"];
|
||||
{improper, Elements} -> ["//erl([", Elements, "])"]
|
||||
end;
|
||||
inspect(Any) when is_tuple(Any) % Record constructors
|
||||
andalso is_atom(element(1, Any))
|
||||
andalso element(1, Any) =/= false
|
||||
andalso element(1, Any) =/= true
|
||||
andalso element(1, Any) =/= nil
|
||||
->
|
||||
[Atom | ArgsList] = erlang:tuple_to_list(Any),
|
||||
InspectedArgs = lists:map(fun inspect/1, ArgsList),
|
||||
case inspect_atom(Atom) of
|
||||
{gleam_atom, GleamAtom} ->
|
||||
Args = lists:join(<<", ">>, InspectedArgs),
|
||||
[GleamAtom, "(", Args, ")"];
|
||||
{erlang_atom, ErlangAtom} ->
|
||||
Args = lists:join(<<", ">>, [ErlangAtom | InspectedArgs]),
|
||||
["#(", Args, ")"]
|
||||
end;
|
||||
inspect(Tuple) when is_tuple(Tuple) ->
|
||||
Elements = lists:map(fun inspect/1, erlang:tuple_to_list(Tuple)),
|
||||
["#(", lists:join(", ", Elements), ")"];
|
||||
inspect(Any) when is_function(Any) ->
|
||||
{arity, Arity} = erlang:fun_info(Any, arity),
|
||||
ArgsAsciiCodes = lists:seq($a, $a + Arity - 1),
|
||||
Args = lists:join(<<", ">>,
|
||||
lists:map(fun(Arg) -> <<Arg>> end, ArgsAsciiCodes)
|
||||
),
|
||||
["//fn(", Args, ") { ... }"];
|
||||
inspect(Any) ->
|
||||
["//erl(", io_lib:format("~p", [Any]), ")"].
|
||||
|
||||
inspect_atom(Atom) ->
|
||||
Binary = erlang:atom_to_binary(Atom),
|
||||
case inspect_maybe_gleam_atom(Binary, none, <<>>) of
|
||||
{ok, Inspected} -> {gleam_atom, Inspected};
|
||||
{error, _} -> {erlang_atom, ["atom.create(\"", Binary, "\")"]}
|
||||
end.
|
||||
|
||||
inspect_maybe_gleam_atom(<<>>, none, _) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<First, _Rest/binary>>, none, _) when ?is_digit_char(First) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, none, _) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<"_">>, _PrevChar, _Acc) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<"_", _Rest/binary>>, $_, _Acc) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<First, _Rest/binary>>, _PrevChar, _Acc)
|
||||
when not (?is_lowercase_char(First) orelse ?is_underscore_char(First) orelse ?is_digit_char(First)) ->
|
||||
{error, nil};
|
||||
inspect_maybe_gleam_atom(<<First, Rest/binary>>, none, Acc) ->
|
||||
inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>);
|
||||
inspect_maybe_gleam_atom(<<"_", Rest/binary>>, _PrevChar, Acc) ->
|
||||
inspect_maybe_gleam_atom(Rest, $_, Acc);
|
||||
inspect_maybe_gleam_atom(<<First, Rest/binary>>, $_, Acc) ->
|
||||
inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, (uppercase(First))>>);
|
||||
inspect_maybe_gleam_atom(<<First, Rest/binary>>, _PrevChar, Acc) ->
|
||||
inspect_maybe_gleam_atom(Rest, First, <<Acc/binary, First>>);
|
||||
inspect_maybe_gleam_atom(<<>>, _PrevChar, Acc) ->
|
||||
{ok, Acc};
|
||||
inspect_maybe_gleam_atom(A, B, C) ->
|
||||
erlang:display({A, B, C}),
|
||||
throw({gleam_error, A, B, C}).
|
||||
|
||||
inspect_list([], _) ->
|
||||
{proper, []};
|
||||
inspect_list([First], true) when ?is_ascii_character(First) ->
|
||||
{charlist, nil};
|
||||
inspect_list([First], _) ->
|
||||
{proper, [inspect(First)]};
|
||||
inspect_list([First | Rest], ValidCharlist) when is_list(Rest) ->
|
||||
StillValidCharlist = ValidCharlist andalso ?is_ascii_character(First),
|
||||
{Kind, Inspected} = inspect_list(Rest, StillValidCharlist),
|
||||
{Kind, [inspect(First), <<", ">> | Inspected]};
|
||||
inspect_list([First | ImproperTail], _) ->
|
||||
{improper, [inspect(First), <<" | ">>, inspect(ImproperTail)]}.
|
||||
|
||||
inspect_bit_array(Bits) ->
|
||||
Text = inspect_bit_array(Bits, <<"<<">>),
|
||||
<<Text/binary, ">>">>.
|
||||
|
||||
inspect_bit_array(<<>>, Acc) ->
|
||||
Acc;
|
||||
inspect_bit_array(<<X, Rest/bitstring>>, Acc) ->
|
||||
inspect_bit_array(Rest, append_segment(Acc, erlang:integer_to_binary(X)));
|
||||
inspect_bit_array(Rest, Acc) ->
|
||||
Size = bit_size(Rest),
|
||||
<<X:Size>> = Rest,
|
||||
X1 = erlang:integer_to_binary(X),
|
||||
Size1 = erlang:integer_to_binary(Size),
|
||||
Segment = <<X1/binary, ":size(", Size1/binary, ")">>,
|
||||
inspect_bit_array(<<>>, append_segment(Acc, Segment)).
|
||||
|
||||
bit_array_to_int_and_size(A) ->
|
||||
Size = bit_size(A),
|
||||
<<A1:Size>> = A,
|
||||
{A1, Size}.
|
||||
|
||||
append_segment(<<"<<">>, Segment) ->
|
||||
<<"<<", Segment/binary>>;
|
||||
append_segment(Acc, Segment) ->
|
||||
<<Acc/binary, ", ", Segment/binary>>.
|
||||
|
||||
|
||||
inspect_maybe_utf8_string(Binary, Acc) ->
|
||||
case Binary of
|
||||
<<>> -> {ok, <<$", Acc/binary, $">>};
|
||||
<<First/utf8, Rest/binary>> ->
|
||||
Escaped = case First of
|
||||
$" -> <<$\\, $">>;
|
||||
$\\ -> <<$\\, $\\>>;
|
||||
$\r -> <<$\\, $r>>;
|
||||
$\n -> <<$\\, $n>>;
|
||||
$\t -> <<$\\, $t>>;
|
||||
$\f -> <<$\\, $f>>;
|
||||
X when X > 126, X < 160 -> convert_to_u(X);
|
||||
X when X < 32 -> convert_to_u(X);
|
||||
Other -> <<Other/utf8>>
|
||||
end,
|
||||
inspect_maybe_utf8_string(Rest, <<Acc/binary, Escaped/binary>>);
|
||||
_ -> {error, not_a_utf8_string}
|
||||
end.
|
||||
|
||||
convert_to_u(Code) ->
|
||||
list_to_binary(io_lib:format("\\u{~4.16.0B}", [Code])).
|
||||
|
||||
float_to_string(Float) when is_float(Float) ->
|
||||
erlang:iolist_to_binary(io_lib_format:fwrite_g(Float)).
|
||||
|
||||
utf_codepoint_list_to_string(List) ->
|
||||
case unicode:characters_to_binary(List) of
|
||||
{error, _} -> erlang:error({gleam_error, {string_invalid_utf8, List}});
|
||||
Binary -> Binary
|
||||
end.
|
||||
|
||||
crop_string(String, Prefix) ->
|
||||
case string:find(String, Prefix) of
|
||||
nomatch -> String;
|
||||
New -> New
|
||||
end.
|
||||
|
||||
contains_string(String, Substring) ->
|
||||
is_bitstring(string:find(String, Substring)).
|
||||
|
||||
base16_encode(Bin) ->
|
||||
PaddedBin = bit_array_pad_to_bytes(Bin),
|
||||
binary:encode_hex(PaddedBin).
|
||||
|
||||
base16_decode(String) ->
|
||||
try
|
||||
{ok, binary:decode_hex(String)}
|
||||
catch
|
||||
_:_ -> {error, nil}
|
||||
end.
|
||||
|
||||
string_replace(String, Pattern, Replacement) ->
|
||||
string:replace(String, Pattern, Replacement, all).
|
||||
|
||||
slice(String, Index, Length) ->
|
||||
case string:slice(String, Index, Length) of
|
||||
X when is_binary(X) -> X;
|
||||
X when is_list(X) -> unicode:characters_to_binary(X)
|
||||
end.
|
||||
|
||||
index([X | _], 0) ->
|
||||
{ok, {some, X}};
|
||||
index([_, X | _], 1) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, X | _], 2) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, _, X | _], 3) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, _, _, X | _], 4) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, _, _, _, X | _], 5) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, _, _, _, _, X | _], 6) ->
|
||||
{ok, {some, X}};
|
||||
index([_, _, _, _, _, _, _, X | _], 7) ->
|
||||
{ok, {some, X}};
|
||||
index(Tuple, Index) when is_tuple(Tuple) andalso is_integer(Index) ->
|
||||
{ok, try
|
||||
{some, element(Index + 1, Tuple)}
|
||||
catch _:_ ->
|
||||
none
|
||||
end};
|
||||
index(Map, Key) when is_map(Map) ->
|
||||
{ok, try
|
||||
{some, maps:get(Key, Map)}
|
||||
catch _:_ ->
|
||||
none
|
||||
end};
|
||||
index(_, Index) when is_integer(Index) ->
|
||||
{error, <<"Indexable">>};
|
||||
index(_, _) ->
|
||||
{error, <<"Dict">>}.
|
||||
|
||||
list(T, A, B, C, D) when is_tuple(T) ->
|
||||
list(tuple_to_list(T), A, B, C, D);
|
||||
list([], _, _, _, Acc) ->
|
||||
{lists:reverse(Acc), []};
|
||||
list([X | Xs], Decode, PushPath, Index, Acc) ->
|
||||
{Out, Errors} = Decode(X),
|
||||
case Errors of
|
||||
[] -> list(Xs, Decode, PushPath, Index + 1, [Out | Acc]);
|
||||
_ -> PushPath({[], Errors}, integer_to_binary(Index))
|
||||
end;
|
||||
list(Unexpected, _, _, _, []) ->
|
||||
Found = gleam@dynamic:classify(Unexpected),
|
||||
Error = {decode_error, <<"List"/utf8>>, Found, []},
|
||||
{[], [Error]};
|
||||
list(_, _, _, _, Acc) ->
|
||||
{lists:reverse(Acc), []}.
|
||||
|
||||
dict(#{} = Data) -> {ok, Data};
|
||||
dict(_) -> {error, nil}.
|
||||
|
||||
int(I) when is_integer(I) -> {ok, I};
|
||||
int(_) -> {error, 0}.
|
||||
|
||||
float(F) when is_float(F) -> {ok, F};
|
||||
float(_) -> {error, 0.0}.
|
||||
|
||||
bit_array(B) when is_bitstring(B) -> {ok, B};
|
||||
bit_array(_) -> {error, <<>>}.
|
||||
|
||||
is_null(X) ->
|
||||
X =:= undefined orelse X =:= null orelse X =:= nil.
|
||||
1048
build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs
Normal file
1048
build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue