diff --git a/.github/workflows/test-doc-examples.yml b/.github/workflows/test-doc-examples.yml new file mode 100644 index 00000000..dfd46974 --- /dev/null +++ b/.github/workflows/test-doc-examples.yml @@ -0,0 +1,21 @@ +name: Test Doc Examples + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 18 + uses: actions/setup-node@v3 + with: + node-version: 18 + - run: npm install + - run: npm run build + - run: npm run test-doc-examples diff --git a/.gitignore b/.gitignore index 41d2024a..be46c65c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,7 @@ lib/bs .merlin .bsb.lock /node_modules/ -.DS_Store \ No newline at end of file +.DS_Store + + +.examples-tests/ diff --git a/package-lock.json b/package-lock.json index 37cc44e6..2deb0ada 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "devDependencies": { "@babel/code-frame": "7.18.6", + "@rescript/tools": "^0.5.0", "rescript": "11.1.0-rc.2" }, "peerDependencies": { @@ -51,6 +52,36 @@ "node": ">=6.9.0" } }, + "node_modules/@rescript/tools": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@rescript/tools/-/tools-0.5.0.tgz", + "integrity": "sha512-gqKZhpXdFMRb0i+aCNKNtbHANFYC/nM7LLLRkkYQLgeJ2teVCV9otO09KIA7CvSZevN6x68r/dkeWi3klLdydA==", + "dev": true, + "dependencies": { + "rescript": "^11.0.0-rc.7" + }, + "bin": { + "rescript-tools": "npm/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@rescript/tools/node_modules/rescript": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/rescript/-/rescript-11.0.1.tgz", + "integrity": "sha512-7T4PRp/d0+CBNnY6PYKffFqo9tGZlvnZpboF/n+8SKS+JZ6VvXJO7W538VPZXf3EYx1COGAWWvkF9e/HgSAqHg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "bsc": "bsc", + "bstracing": "lib/bstracing", + "rescript": "rescript" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", diff --git a/package.json b/package.json index df1eefc2..5d807853 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "clean": "rescript clean", "build": "rescript", "watch": "rescript build -w", - "test": "node test/TestSuite.mjs && node test/TempTests.mjs" + "test": "node test/TestSuite.mjs && node test/TempTests.mjs", + "test-doc-examples": "node scripts/DocTests.mjs" }, "keywords": [ "rescript" @@ -26,7 +27,8 @@ "rescript": ">=11.0.0 || ^11.1.0-rc.2" }, "devDependencies": { - "rescript": "11.1.0-rc.2", - "@babel/code-frame": "7.18.6" + "@babel/code-frame": "7.18.6", + "@rescript/tools": "^0.5.0", + "rescript": "11.1.0-rc.2" } } diff --git a/rescript.json b/rescript.json index f5c04d1e..e1560e31 100644 --- a/rescript.json +++ b/rescript.json @@ -9,6 +9,10 @@ { "dir": "test", "type": "dev" + }, + { + "dir": "scripts", + "type": "dev" } ], "suffix": ".mjs", @@ -16,6 +20,7 @@ "module": "es6", "in-source": true }, + "bs-dev-dependencies": ["@rescript/tools"], "warnings": { "error": "+101" } diff --git a/scripts/DocTests.mjs b/scripts/DocTests.mjs new file mode 100644 index 00000000..d07cd4bd --- /dev/null +++ b/scripts/DocTests.mjs @@ -0,0 +1,380 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Fs from "fs"; +import * as Os from "os"; +import * as Url from "url"; +import * as Path from "path"; +import * as Belt_List from "rescript/lib/es6/belt_List.js"; +import * as Belt_Array from "rescript/lib/es6/belt_Array.js"; +import * as Core__List from "../src/Core__List.mjs"; +import * as Core__Array from "../src/Core__Array.mjs"; +import * as RescriptCore from "../src/RescriptCore.mjs"; +import * as Tools_Docgen from "@rescript/tools/npm/Tools_Docgen.mjs"; +import * as Child_process from "child_process"; +import * as Promises from "node:fs/promises"; + +var Path$1 = {}; + +var $$URL = {}; + +var Process = {}; + +var Fs$1 = {}; + +var $$Buffer = {}; + +var ChildProcess = {}; + +var OS = {}; + +var $$Node = { + Path: Path$1, + $$URL: $$URL, + Process: Process, + Fs: Fs$1, + $$Buffer: $$Buffer, + ChildProcess: ChildProcess, + OS: OS +}; + +var dirname = Path.dirname(Url.fileURLToPath(import.meta.url)); + +var compilerDir = Path.join(dirname, "..", ".examples-tests"); + +var rescriptBin = Path.join(compilerDir, "node_modules", ".bin", "rescript"); + +var bscBin = Path.join(compilerDir, "node_modules", ".bin", "bsc"); + +var rescriptCoreCompiled = Path.join(compilerDir, "node_modules", "@rescript", "core", "lib", "ocaml"); + +function makePackageJson(coreVersion) { + return "{\n \"name\": \"test-compiler-examples\",\n \"version\": \"1.0.0\",\n \"dependencies\": {\n \"@rescript/core\": \"file:rescript-core-" + coreVersion + ".tgz\",\n \"rescript\": \"^11.0.1\"\n }\n}\n"; +} + +var rescriptJson = "{\n \"name\": \"dummy\",\n \"sources\": {\n \"dir\": \"dummy\",\n \"subdirs\": true\n },\n \"bs-dependencies\": [\n \"@rescript/core\"\n ],\n \"bsc-flags\": [\n \"-open RescriptCore\"\n ]\n}"; + +function prepareCompiler() { + var corePath = Path.join(compilerDir, ".."); + if (!Fs.existsSync(compilerDir)) { + Fs.mkdirSync(compilerDir); + } + Child_process.execFileSync("npm", [ + "pack", + corePath + ], { + stdio: "ignore", + cwd: compilerDir + }); + var dict = JSON.parse(Fs.readFileSync(Path.join(corePath, "package.json"))); + var currentCoreVersion; + if (!Array.isArray(dict) && (dict === null || typeof dict !== "object") && typeof dict !== "number" && typeof dict !== "string" && typeof dict !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "DocTests.res", + 128, + 9 + ], + Error: new Error() + }; + } + if (typeof dict === "object" && !Array.isArray(dict)) { + var s = dict["version"]; + if (!Array.isArray(s) && (s === null || typeof s !== "object") && typeof s !== "number" && typeof s !== "string" && typeof s !== "boolean") { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "DocTests.res", + 126, + 11 + ], + Error: new Error() + }; + } + if (typeof s === "string") { + currentCoreVersion = s; + } else { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "DocTests.res", + 126, + 11 + ], + Error: new Error() + }; + } + } else { + throw { + RE_EXN_ID: "Assert_failure", + _1: [ + "DocTests.res", + 128, + 9 + ], + Error: new Error() + }; + } + Fs.writeFileSync(Path.join(compilerDir, "package.json"), makePackageJson(currentCoreVersion)); + Fs.writeFileSync(Path.join(compilerDir, "rescript.json"), rescriptJson); + var dummyFolder = Path.join(compilerDir, "dummy"); + if (!Fs.existsSync(dummyFolder)) { + Fs.mkdirSync(dummyFolder); + } + Child_process.execFileSync("npm", ["install"], { + cwd: compilerDir + }); + Child_process.execFileSync(rescriptBin, ["build"], { + cwd: compilerDir + }); +} + +prepareCompiler(); + +function createFileInTempDir(id) { + return Path.join(Os.tmpdir(), id); +} + +async function testCode(id, code) { + var tempFileName = Path.join(Os.tmpdir(), id); + await Promises.writeFile(tempFileName + ".res", code); + var args = [ + tempFileName + ".res", + "-I", + rescriptCoreCompiled, + "-w", + "-109", + "-uncurried", + "-open", + "RescriptCore" + ]; + var promise = await new Promise((function (resolve, _reject) { + var spawn = Child_process.spawn(bscBin, args); + var stderr = []; + spawn.stderr.on("data", (function (data) { + stderr.push(data); + })); + spawn.once("close", (function (_code, _signal) { + resolve(stderr); + })); + })); + if (promise.length > 0) { + return { + TAG: "Error", + _0: promise.map(function (e) { + return e.toString(); + }).join("") + }; + } else { + return { + TAG: "Ok", + _0: undefined + }; + } +} + +function extractDocFromFile(file) { + var toolsBin = Path.join(Path.dirname(dirname), "node_modules", ".bin", "rescript-tools"); + var spawn = Child_process.spawnSync(toolsBin, [ + "doc", + file + ]); + return Tools_Docgen.decodeFromJson(JSON.parse(spawn.stdout.toString())); +} + +function getExamples(param) { + var loop = function (_items, _acc) { + while(true) { + var acc = _acc; + var items = _items; + if (!items) { + return acc; + } + var match = items.hd; + switch (match.kind) { + case "value" : + _acc = { + hd: { + id: match.id, + kind: "value", + name: match.name, + docstrings: match.docstrings + }, + tl: acc + }; + _items = items.tl; + continue ; + case "type" : + _acc = { + hd: { + id: match.id, + kind: "type", + name: match.name, + docstrings: match.docstrings + }, + tl: acc + }; + _items = items.tl; + continue ; + case "module" : + _acc = { + hd: { + id: match.id, + kind: "module", + name: match.name, + docstrings: match.docstrings + }, + tl: acc + }; + _items = Belt_List.concatMany([ + items.tl, + Core__List.fromArray(match.items) + ]); + continue ; + case "moduleAlias" : + _acc = { + hd: { + id: match.id, + kind: "moduleAlias", + name: match.name, + docstrings: match.docstrings + }, + tl: acc + }; + _items = Belt_List.concatMany([ + items.tl, + Core__List.fromArray(match.items) + ]); + continue ; + + } + }; + }; + return Core__List.toArray(loop(Core__List.fromArray(param.items), /* [] */0)).filter(function (param) { + return param.docstrings.length > 0; + }); +} + +function getCodeBlocks(example) { + var loopEndCodeBlock = function (_lines, _acc) { + while(true) { + var acc = _acc; + var lines = _lines; + if (!lines) { + return RescriptCore.panic("Failed to find end of code block for " + example.kind + ": " + example.id); + } + var hd = lines.hd; + if (hd.trim().endsWith("```")) { + return acc; + } + _acc = { + hd: hd, + tl: acc + }; + _lines = lines.tl; + continue ; + }; + }; + var loop = function (_lines, _acc) { + while(true) { + var acc = _acc; + var lines = _lines; + if (!lines) { + return acc; + } + var rest = lines.tl; + if (lines.hd.trim().startsWith("```res")) { + var code = loopEndCodeBlock(rest, /* [] */0); + _acc = { + hd: Core__List.toArray(Core__List.reverse(code)).join("\n"), + tl: acc + }; + _lines = rest; + continue ; + } + _lines = rest; + continue ; + }; + }; + return Core__List.toArray(loop(Core__List.fromArray(Core__Array.reduce(example.docstrings, [], (function (acc, docstring) { + return acc.concat(docstring.split("\n")); + }))), /* [] */0)); +} + +async function main() { + var results = await Promise.all(getExamples(extractDocFromFile("src/RescriptCore.res")).map(async function (example) { + var id = example.id.replaceAll(".", "_"); + var codes = getCodeBlocks(example); + var results = await Promise.all(codes.map(async function (code, $$int) { + var id$1 = id + "_" + $$int.toString(); + return await testCode(id$1, code); + })); + return [ + example, + results + ]; + })); + var errors = Belt_Array.keepMap(results, (function (param) { + var errors = Belt_Array.keepMap(param[1], (function (result) { + if (result.TAG === "Ok") { + return ; + } else { + return result._0; + } + })); + if (errors.length > 0) { + return [ + param[0], + errors + ]; + } + + })); + errors.forEach(function (param) { + var test = param[0]; + var cyan = function (s) { + return "\x1b[36m" + s + "\x1b[0m"; + }; + var other = test.kind; + var kind = other === "moduleAlias" ? "module alias" : other; + var errorMessage = param[1].map(function (e) { + return e.split("\n").filter(function (param, i) { + return i !== 2; + }).join("\n"); + }).join("\n"); + var message = "\x1B[1;31merror\x1B[0m: failed to compile examples from " + kind + " " + cyan(test.id) + "\n" + errorMessage; + process.stderr.write(message); + }); + if (errors.length === 0) { + return 0; + } else { + return 1; + } +} + +var exitCode = await main(); + +process.exit(exitCode); + +var Docgen; + +export { + $$Node , + Docgen , + dirname , + compilerDir , + rescriptBin , + bscBin , + rescriptCoreCompiled , + makePackageJson , + rescriptJson , + prepareCompiler , + createFileInTempDir , + testCode , + extractDocFromFile , + getExamples , + getCodeBlocks , + main , + exitCode , +} +/* dirname Not a pure module */ diff --git a/scripts/DocTests.res b/scripts/DocTests.res new file mode 100644 index 00000000..2eb81eb2 --- /dev/null +++ b/scripts/DocTests.res @@ -0,0 +1,341 @@ +module Node = { + module Path = { + @module("path") external join2: (string, string) => string = "join" + @module("path") @variadic external join: array => string = "join" + @module("path") external dirname: string => string = "dirname" + } + + module URL = { + @module("url") external fileURLToPath: string => string = "fileURLToPath" + } + + module Process = { + @scope("process") external exit: int => unit = "exit" + @scope(("process", "stderr")) + external stderrWrite: string => unit = "write" + } + + module Fs = { + @module("fs") external readFileSync: string => string = "readFileSync" + @module("fs") external writeFileSync: (string, string) => unit = "writeFileSync" + @module("fs") external mkdirSync: string => option = "mkdirSync" + @module("fs") external existsSync: string => bool = "existsSync" + @module("node:fs/promises") external writeFile: (string, string) => promise = "writeFile" + @module("node:fs/promises") external unlink: string => promise = "unlink" + @module("node:fs/promises") external lstat: string => promise<'a> = "lstat" + } + + module Buffer = { + type t + @send external toString: t => string = "toString" + } + + module ChildProcess = { + type execSyncOpts = {stdio?: string, cwd?: string} + @module("child_process") + external execFileSync: (string, array, execSyncOpts) => Buffer.t = "execFileSync" + + type spawnSyncReturns = {stdout: Buffer.t} + @module("child_process") + external spawnSync: (string, array) => spawnSyncReturns = "spawnSync" + + type readable + type spawnReturns = {stderr: readable} + @module("child_process") + external spawn: (string, array) => spawnReturns = "spawn" + + @send external on: (readable, string, Buffer.t => unit) => unit = "on" + @send + external once: (spawnReturns, string, (Js.Null.t, Js.Null.t) => unit) => unit = + "once" + } + + module OS = { + @module("os") + external tmpdir: unit => string = "tmpdir" + } +} + +open RescriptCore +open Node + +module Docgen = RescriptTools.Docgen + +@val @scope(("import", "meta")) external url: string = "url" + +let dirname = + url + ->URL.fileURLToPath + ->Path.dirname + +let compilerDir = Path.join([dirname, "..", ".examples-tests"]) + +let rescriptBin = Path.join([compilerDir, "node_modules", ".bin", "rescript"]) + +let bscBin = Path.join([compilerDir, "node_modules", ".bin", "bsc"]) + +let rescriptCoreCompiled = Path.join([ + compilerDir, + "node_modules", + "@rescript", + "core", + "lib", + "ocaml", +]) + +let makePackageJson = coreVersion => + `{ + "name": "test-compiler-examples", + "version": "1.0.0", + "dependencies": { + "@rescript/core": "file:rescript-core-${coreVersion}.tgz", + "rescript": "^11.0.1" + } +} +` + +let rescriptJson = `{ + "name": "dummy", + "sources": { + "dir": "dummy", + "subdirs": true + }, + "bs-dependencies": [ + "@rescript/core" + ], + "bsc-flags": [ + "-open RescriptCore" + ] +}` + +let prepareCompiler = () => { + let corePath = Path.join([compilerDir, ".."]) + + if !Fs.existsSync(compilerDir) { + Fs.mkdirSync(compilerDir)->ignore + } + + ChildProcess.execFileSync("npm", ["pack", corePath], {cwd: compilerDir, stdio: "ignore"})->ignore + + let currentCoreVersion = switch Path.join2(corePath, "package.json") + ->Fs.readFileSync + ->JSON.parseExn { + | Object(dict) => + switch dict->Dict.getUnsafe("version") { + | String(s) => s + | _ => assert(false) + } + | _ => assert(false) + } + + Path.join2(compilerDir, "package.json")->Fs.writeFileSync(makePackageJson(currentCoreVersion)) + Path.join2(compilerDir, "rescript.json")->Fs.writeFileSync(rescriptJson) + + let dummyFolder = Path.join2(compilerDir, "dummy") + + if !Fs.existsSync(dummyFolder) { + Fs.mkdirSync(dummyFolder)->ignore + } + + ChildProcess.execFileSync("npm", ["install"], {cwd: compilerDir})->ignore + + ChildProcess.execFileSync(rescriptBin, ["build"], {cwd: compilerDir})->ignore +} + +prepareCompiler() + +type example = { + id: string, + kind: string, + name: string, + docstrings: array, +} + +let createFileInTempDir = id => Path.join2(OS.tmpdir(), id) + +let testCode = async (~id, ~code) => { + let tempFileName = createFileInTempDir(id) + + let () = await Fs.writeFile(tempFileName ++ ".res", code) + + let args = [ + tempFileName ++ ".res", + "-I", + rescriptCoreCompiled, + "-w", + "-109", + "-uncurried", + "-open", + "RescriptCore", + ] + + let promise = await Promise.make((resolve, _reject) => { + let spawn = ChildProcess.spawn(bscBin, args) + let stderr = [] + spawn.stderr->ChildProcess.on("data", data => { + Array.push(stderr, data) + }) + spawn->ChildProcess.once("close", (_code, _signal) => { + resolve(stderr) + }) + }) + + switch Array.length(promise) > 0 { + | true => + promise + ->Array.map(e => e->Buffer.toString) + ->Array.joinWith("") + ->Error + | false => Ok() + } +} + +let extractDocFromFile = file => { + let toolsBin = Path.join([Path.dirname(dirname), "node_modules", ".bin", "rescript-tools"]) + let spawn = ChildProcess.spawnSync(toolsBin, ["doc", file]) + + spawn.stdout + ->Buffer.toString + ->JSON.parseExn + ->Docgen.decodeFromJson +} + +let getExamples = ({items}: Docgen.doc) => { + let rec loop = (items: list, acc: list) => { + switch items { + | list{Value({docstrings, id, name}), ...rest} => + loop(rest, list{{id, name, docstrings, kind: "value"}, ...acc}) + | list{Type({docstrings, id, name}), ...rest} => + loop(rest, list{{id, name, docstrings, kind: "type"}, ...acc}) + | list{Module({id, name, docstrings, items}), ...rest} => + loop( + list{...rest, ...List.fromArray(items)}, + list{{id, name, docstrings, kind: "module"}, ...acc}, + ) + | list{ModuleAlias({id, name, docstrings, items}), ...rest} => + loop( + list{...rest, ...List.fromArray(items)}, + list{{id, name, docstrings, kind: "moduleAlias"}, ...acc}, + ) + | list{} => acc + } + } + + items + ->List.fromArray + ->loop(list{}) + ->List.toArray + ->Array.filter(({docstrings}) => Array.length(docstrings) > 0) +} + +let getCodeBlocks = example => { + let rec loopEndCodeBlock = (lines, acc) => { + switch lines { + | list{hd, ...rest} => + if ( + hd + ->String.trim + ->String.endsWith("```") + ) { + acc + } else { + loopEndCodeBlock(rest, list{hd, ...acc}) + } + | list{} => panic(`Failed to find end of code block for ${example.kind}: ${example.id}`) + } + } + + let rec loop = (lines: list, acc: list) => { + switch lines { + | list{hd, ...rest} => + switch hd + ->String.trim + ->String.startsWith("```res") { + | true => + let code = loopEndCodeBlock(rest, list{}) + loop( + rest, + list{ + code + ->List.reverse + ->List.toArray + ->Array.joinWith("\n"), + ...acc, + }, + ) + | false => loop(rest, acc) + } + | list{} => acc + } + } + + example.docstrings + ->Array.reduce([], (acc, docstring) => acc->Array.concat(docstring->String.split("\n"))) + ->List.fromArray + ->loop(list{}) + ->List.toArray +} + +let main = async () => { + let results = + await extractDocFromFile("src/RescriptCore.res") + ->getExamples + ->Array.map(async example => { + let id = example.id->String.replaceAll(".", "_") + let codes = example->getCodeBlocks + let results = + await codes + ->Array.mapWithIndex(async (code, int) => { + let id = `${id}_${Int.toString(int)}` + await testCode(~id, ~code) + }) + ->Promise.all + (example, results) + }) + ->Promise.all + + let errors = results->Belt.Array.keepMap(((example, results)) => { + let errors = results->Belt.Array.keepMap(result => + switch result { + | Ok() => None + | Error(msg) => Some(msg) + } + ) + + if Array.length(errors) > 0 { + Some((example, errors)) + } else { + None + } + }) + + // Print Errors + let () = errors->Array.forEach(((test, errors)) => { + let red = s => `\x1B[1;31m${s}\x1B[0m` + let cyan = s => `\x1b[36m${s}\x1b[0m` + let kind = switch test.kind { + | "moduleAlias" => "module alias" + | other => other + } + + let errorMessage = + errors + ->Array.map(e => { + // Drop line from path file + e + ->String.split("\n") + ->Array.filterWithIndex((_, i) => i !== 2) + ->Array.joinWith("\n") + }) + ->Array.joinWith("\n") + + let message = `${"error"->red}: failed to compile examples from ${kind} ${test.id->cyan}\n${errorMessage}` + + Process.stderrWrite(message) + }) + + errors->Array.length == 0 ? 0 : 1 +} +let exitCode = await main() + +Process.exit(exitCode) diff --git a/src/Core__Array.resi b/src/Core__Array.resi index 4cce0701..7fb2aae5 100644 --- a/src/Core__Array.resi +++ b/src/Core__Array.resi @@ -36,7 +36,7 @@ let make: (~length: int, 'a) => array<'a> Creates an array of length `length` initialized with the value returned from `f ` for each index. ```res example - Array.make(~length=3, i => i + 3) == [3, 4, 5] + Array.fromInitializer(~length=3, i => i + 3) == [3, 4, 5] ``` */ let fromInitializer: (~length: int, int => 'a) => array<'a> @@ -622,8 +622,11 @@ type languages = ReScript | TypeScript | JavaScript let array = [ReScript, JavaScript] -Console.log(array->Array.findIndexWithIndex((item, index) => index === 0 && item == ReScript)) // 0 -Console.log(array->Array.findIndex((item, index) => index === 0 && item == TypeScript)) // -1 +let isReScriptFirst = array->Array.findIndexWithIndex((item, index) => index === 0 && item == ReScript) +let isTypeScriptFirst = array->Array.findIndexWithIndex((item, index) => index === 0 && item == TypeScript) + +Console.log(isReScriptFirst) // 0 +Console.log(isTypeScriptFirst) // -1 ``` */ @send @@ -739,7 +742,7 @@ let reduceRight: (array<'a>, 'b, ('b, 'a) => 'b) => 'b Like `reduceRight`, but with an additional index argument on the callback function. ```res example - Array.reduceRightWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i, 0) == 16 + Array.reduceRightWithIndex([1, 2, 3, 4], 0, (acc, x, i) => acc + x + i) == 16 ``` */ let reduceRightWithIndex: (array<'a>, 'b, ('b, 'a, int) => 'b) => 'b @@ -818,6 +821,7 @@ Use `Array.getUnsafe` only when you are sure the `index` exists (i.e. when using ## Examples ```rescript +let array = [1, 2, 3] for index in 0 to array->Array.length - 1 { let value = array->Array.getUnsafe(index) Console.log(value) @@ -971,7 +975,7 @@ external flatMap: (array<'a>, 'a => array<'b>) => array<'b> = "flatMap" Otherwise returns `None` ```res example - Array.findMap([1, 2, 3], n => mod(n, 2) ? Some(n - 2) : None) == 0 + Array.findMap([1, 2, 3], n => mod(n, 2) == 0 ? Some(n - 2) : None) == Some(0) // true ``` */ let findMap: (array<'a>, 'a => option<'b>) => option<'b> diff --git a/src/Core__AsyncIterator.resi b/src/Core__AsyncIterator.resi index 49e0864b..c97bc6ec 100644 --- a/src/Core__AsyncIterator.resi +++ b/src/Core__AsyncIterator.resi @@ -29,7 +29,8 @@ See [async iterator protocols](https://developer.mozilla.org/en-US/docs/Web/Java ## Examples - A simple example, getting the next value: ```rescript -let {done, value} = await someAsyncIterator->AsyncIterator.next +@val external asyncIterator: AsyncIterator.t = "someAsyncIterator" +let {AsyncIterator.done, value} = await asyncIterator->AsyncIterator.next ``` - Complete example, including looping over all values: diff --git a/src/Core__Console.resi b/src/Core__Console.resi index 41c7b9fc..ec1d757a 100644 --- a/src/Core__Console.resi +++ b/src/Core__Console.resi @@ -14,7 +14,7 @@ on MDN. ```rescript Console.assert_(false, "Hello World!") -Console.assert_(n == 42, "The answer") +Console.assert_(42 == 42, "The answer") ``` */ @val @@ -27,7 +27,7 @@ external assert_: (bool, 'a) => unit = "console.assert" ```rescript Console.assert2(false, "Hello", "World") -Console.assert2(n == 42, [1, 2, 3], '4') +Console.assert2(42 == 42, [1, 2, 3], '4') ``` */ @val @@ -40,7 +40,7 @@ external assert2: (bool, 'a, 'b) => unit = "console.assert" ```rescript Console.assert3(false, "Hello", "World", "ReScript") -Console.assert3(n == 42, "One", 2, #3) +Console.assert3(42 == 42, "One", 2, #3) ``` */ @val @@ -52,8 +52,9 @@ external assert3: (bool, 'a, 'b, 'c) => unit = "console.assert" ## Examples ```rescript +let value = 42 Console.assert4(false, "Hello", "World", "ReScript", "!!!") -Console.assert4(m == 42, [1, 2], (3, 4), [#5, #6], #"polyvar") +Console.assert4(value == 42, [1, 2], (3, 4), [#5, #6], #"polyvar") ``` */ @val @@ -65,8 +66,9 @@ external assert4: (bool, 'a, 'b, 'c, 'd) => unit = "console.assert" ## Examples ```rescript +let value = 42 Console.assert5(false, "Hello", "World", "JS", '!', '!') -Console.assert5(n == 42, [1, 2], (3, 4), [#5, #6], #"polyvar", {"name": "ReScript"}) +Console.assert5(value == 42, [1, 2], (3, 4), [#5, #6], #"polyvar", {"name": "ReScript"}) ``` */ @val @@ -78,8 +80,9 @@ external assert5: (bool, 'a, 'b, 'c, 'd, 'e) => unit = "console.assert" ## Examples ```rescript +let value = 42 Console.assert6(false, "Hello", "World", "JS", '!', '!', '?') -Console.assert6(n == 42, [1, 2], (3, 4), [#5, #6], #"polyvar", {"name": "ReScript"}, 42) +Console.assert6(value == 42, [1, 2], (3, 4), [#5, #6], #"polyvar", {"name": "ReScript"}, 42) ``` */ @val @@ -91,8 +94,9 @@ external assert6: (bool, 'a, 'b, 'c, 'd, 'e, 'f) => unit = "console.assert" ## Examples ```rescript +let value = 42 Console.assertMany(false, ["Hello", "World"]) -Console.assertMany(n == 42, [1, 2, 3]) +Console.assertMany(value == 42, [1, 2, 3]) ``` */ @val @@ -249,7 +253,7 @@ on MDN. ## Examples ```rescript -Console.dir({"language": "rescript", "version": 10.1.2}) +Console.dir({"language": "rescript", "version": "10.1.2"}) ``` */ @val @@ -325,7 +329,7 @@ external error4: ('a, 'b, 'c, 'd) => unit = "console.error" ## Examples ```rescript -Console.error5('e', 'r, 'r', 'o', 'r') +Console.error5('e', 'r', 'r', 'o', 'r') Console.error5(1, #second, #third, ("fourth"), 'c') ``` */ @@ -597,7 +601,7 @@ on MDN. ## Examples ```rescript -Console.table({"language": "rescript", "version": 10.1.2}) +Console.table({"language": "rescript", "version": "10.1.2"}) ``` */ @val diff --git a/src/Core__Date.resi b/src/Core__Date.resi index e07676e1..5df89c53 100644 --- a/src/Core__Date.resi +++ b/src/Core__Date.resi @@ -67,20 +67,15 @@ You can use the result like any valid date, but many functions like `toString` w ## Examples ```rescript -Date.fromString("2023") -// 2023-01-01T00:00:00.000Z +Date.fromString("2023") // 2023-01-01T00:00:00.000Z -Date.fromString("2023-02-20") -// 2023-02-20T00:00:00.000Z +Date.fromString("2023-02-20") // 2023-02-20T00:00:00.000Z -Date.fromString("2023-02-20T16:40:00.00Z") -// 2023-02-20T16:40:00.000Z +Date.fromString("2023-02-20T16:40:00.00Z") // 2023-02-20T16:40:00.000Z -Date.fromString("") -// Invalid Date +Date.fromString("") // Invalid Date -Date.fromString("")->getTime -// NaN +Date.fromString("")->Date.getTime // NaN ``` */ @new @@ -801,8 +796,7 @@ Returns the year of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCFullYear -// 2022 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCFullYear // 2022 ``` */ @send @@ -815,8 +809,7 @@ Returns the month of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCMonth -// 11 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCMonth // 11 ``` */ @send @@ -829,8 +822,7 @@ Returns the date (day of month) of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCDate -// 31 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCDate // 31 ``` */ @send @@ -843,8 +835,7 @@ Returns the hours of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCHours -// 23 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCHours // 23 ``` */ @send @@ -857,8 +848,7 @@ Returns the minutes of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCMinutes -// 0 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCMinutes // 0 ``` */ @send @@ -871,8 +861,7 @@ Returns the seconds of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCSeconds -// 0 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCSeconds // 0 ``` */ @send @@ -885,8 +874,7 @@ Returns the milliseconds of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCMilliseconds -// 0 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCMilliseconds // 0 ``` */ @send @@ -900,8 +888,7 @@ Returns the day (day of week) of a given date (according to UTC time). ## Examples ```rescript -Date.fromString("2023-01-01T00:00:00.00+01:00").getUTCDay -// 6 +Date.fromString("2023-01-01T00:00:00.00+01:00")->Date.getUTCDay // 6 ``` */ @send diff --git a/src/Core__Dict.resi b/src/Core__Dict.resi index 5ca553e1..f0cec3fa 100644 --- a/src/Core__Dict.resi +++ b/src/Core__Dict.resi @@ -17,11 +17,9 @@ Use `Dict.getUnsafe` only when you are sure the key exists (i.e. when iterating ## Examples ```rescript -let keys = dict->Dict.keys -keys->Array.forEach(key => { - let value = dict->Dict.getUnsafe(key) - Console.log(value) -}) +let dict = Dict.fromArray([("key1", "value1"), ("key2", "value2")]) +let value = dict->Dict.getUnsafe("key1") +Console.log(value) // value1 ``` */ @get_index diff --git a/src/Core__Error.resi b/src/Core__Error.resi index 76c12c0c..38b6a973 100644 --- a/src/Core__Error.resi +++ b/src/Core__Error.resi @@ -28,7 +28,8 @@ See [`Error.prototype.stack`](https://developer.mozilla.org/en-US/docs/Web/JavaS ## Example ```rescript -Console.log(someError->Error.stack) // Logs `stack` if it exists on `someError` +let error = Error.make("error") +Console.log(error->Error.stack) // Logs `stack` if it exists on `someError` ``` */ @get diff --git a/src/Core__Float.resi b/src/Core__Float.resi index 82bc5fcd..8fe04228 100644 --- a/src/Core__Float.resi +++ b/src/Core__Float.resi @@ -153,7 +153,7 @@ See [`parseFloat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ```rescript Float.parseFloat("1.0") // 1.0 Float.parseFloat(" 3.14 ") // 3.14 -Float.parseFloat(3.0) // 3.0 +Float.parseFloat("3.0") // 3.0 Float.parseFloat("3.14some non-digit characters") // 3.14 Float.parseFloat("error")->Float.isNaN // true ``` @@ -190,10 +190,10 @@ See [`parseInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Referen ## Examples ```rescript -Float.parseInt("10.0", ~radix=2) // 2.0 -Float.parseInt("15 * 3", ~radix=10) // 15.0 -Float.parseInt("12", ~radix=13) // 15.0 -Float.parseInt("17", ~radix=40)->Float.isNaN // true +Float.parseIntWithRadix("10.0", ~radix=2) // 2.0 +Float.parseIntWithRadix("15 * 3", ~radix=10) // 15.0 +Float.parseIntWithRadix("12", ~radix=13) // 15.0 +Float.parseIntWithRadix("17", ~radix=40)->Float.isNaN // true ``` */ @val @@ -258,8 +258,8 @@ See [`Number.toFixed`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ## Examples ```rescript -Float.toFixed(300.0, ~digits=4) // "300.0000" -Float.toFixed(300.0, ~digits=1) // "300.0" +Float.toFixedWithPrecision(300.0, ~digits=4) // "300.0000" +Float.toFixedWithPrecision(300.0, ~digits=1) // "300.0" ``` ## Exceptions @@ -286,15 +286,15 @@ Float.toPrecision(1.0) // "1" external toPrecision: float => string = "toPrecision" /** -`toPrecision(v, ~digits)` return a `string` representing the giver value with +`toPrecisionWithPrecision(v, ~digits)` return a `string` representing the giver value with precision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN. ## Examples ```rescript -Float.toPrecision(100.0, ~digits=2) // "1.0e+2" -Float.toPrecision(1.0) // "1.0" +Float.toPrecisionWithPrecision(100.0, ~digits=2) // "1.0e+2" +Float.toPrecisionWithPrecision(1.0, ~digits=1) // "1" ``` ## Exceptions @@ -329,8 +329,8 @@ See [`Number.toString`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/ ## Examples ```rescript -Float.toString(6.0, ~radix=2) // "110" -Float.toString(3735928559.0, ~radix=16) // "deadbeef" +Float.toStringWithRadix(6.0, ~radix=2) // "110" +Float.toStringWithRadix(3735928559.0, ~radix=16) // "deadbeef" Float.toStringWithRadix(123456.0, ~radix=36) // "2n9c" ``` @@ -350,10 +350,10 @@ See [`Number.toLocaleString`](https://developer.mozilla.org/en-US/docs/Web/JavaS ```rescript // If the application uses English as the default language -Int.toLocaleString(1000.0) // "1,000" +Float.toLocaleString(1000.0) // "1,000" // If the application uses Portuguese Brazil as the default language -Int.toLocaleString(1000.0) // "1.000" +Float.toLocaleString(1000.0) // "1.000" ``` */ @send @@ -404,7 +404,7 @@ external fromInt: int => float = "%identity" ## Examples ```rescript -Int.mod(7.0, 4.0) == 3 +Float.mod(7.0, 4.0) == 3.0 ``` */ external mod: (float, float) => float = "?fmod_float" @@ -417,10 +417,10 @@ if `max` < `min` returns `min`. ## Examples ```rescript -Int.clamp(4.2) == 4.2 -Int.clamp(4.2, ~min=4.3) == 4.3 -Int.clamp(4.2, ~max=4.1) == 4.1 -Int.clamp(4.2, ~min=4.3, ~max=4.1) == 4.3 +Float.clamp(4.2) == 4.2 +Float.clamp(4.2, ~min=4.3) == 4.3 +Float.clamp(4.2, ~max=4.1) == 4.1 +Float.clamp(4.2, ~min=4.3, ~max=4.1) == 4.3 ``` */ let clamp: (~min: float=?, ~max: float=?, float) => float diff --git a/src/Core__Int.resi b/src/Core__Int.resi index 44729e1b..37199db3 100644 --- a/src/Core__Int.resi +++ b/src/Core__Int.resi @@ -121,8 +121,8 @@ on MDN. ## Examples ```rescript -Int.toFixed(300, ~digits=4) // "300.0000" -Int.toFixed(300, ~digits=1) // "300.0" +Int.toFixedWithPrecision(300, ~digits=4) // "300.0000" +Int.toFixedWithPrecision(300, ~digits=1) // "300.0" ``` ## Exceptions @@ -148,14 +148,14 @@ Int.toPrecision(1) // "1" external toPrecision: int => string = "toPrecision" /** -`toPrecision(n, ~digits)` return a `string` representing the giver value with +`toPrecisionWithPrecision(n, ~digits)` return a `string` representing the giver value with precision. `digits` specifies the number of significant digits. See [`Number.toPrecision`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toPrecision) on MDN. ## Examples ```rescript -Int.toPrecision(100, ~digits=2) // "1.0e+2" -Int.toPrecision(1) // "1.0" +Int.toPrecisionWithPrecision(100, ~digits=2) // "1.0e+2" +Int.toPrecisionWithPrecision(1, ~digits=2) // "1.0" ``` ## Exceptions @@ -192,8 +192,8 @@ on MDN. ## Examples ```rescript -Int.toString(6, ~radix=2) // "110" -Int.toString(3735928559, ~radix=16) // "deadbeef" +Int.toStringWithRadix(6, ~radix=2) // "110" +Int.toStringWithRadix(373592855, ~radix=16) // "16449317" Int.toStringWithRadix(123456, ~radix=36) // "2n9c" ``` diff --git a/src/Core__Iterator.resi b/src/Core__Iterator.resi index 4953614d..dc67deb5 100644 --- a/src/Core__Iterator.resi +++ b/src/Core__Iterator.resi @@ -30,8 +30,9 @@ See [iterator protocols](https://developer.mozilla.org/en-US/docs/Web/JavaScript ## Examples ```rescript +@val external someIterator: Iterator.t = "someIterator" // Pulls out the next value of the iterator -let {done, value} = someIterator->Iterator.next +let {Iterator.done, value} = someIterator->Iterator.next ``` */ @send diff --git a/src/Core__JSON.resi b/src/Core__JSON.resi index a5636ed7..34bf688c 100644 --- a/src/Core__JSON.resi +++ b/src/Core__JSON.resi @@ -29,7 +29,7 @@ try { let _ = JSON.parseExn("") // error } catch { -| Exn.Error(obj) => Console.log("error") +| Exn.Error(_) => Console.log("error") } ``` @@ -50,7 +50,7 @@ It returns a JSON type. ## Examples ```rescript -let reviver = (key, value) => { +let reviver = (_, value) => { let valueType = JSON.Classify.classify(value) switch valueType { @@ -145,7 +145,7 @@ let json = ("someNumber", JSON.Encode.int(42)), ])->JSON.Encode.object -let replacer = (key, value) => { +let replacer = (_, value) => { let decodedValue = value->JSON.Decode.string switch decodedValue { @@ -162,7 +162,7 @@ JSON.stringifyWithReplacer(json, replacer) external stringifyWithReplacer: (t, (string, t) => t) => string = "JSON.stringify" /** -`stringifyWithReplacerAndIndent(json, replacer, indentation)` +`stringifyWithReplacerAndIndent(json, replacer, indentation)` Converts a JSON object to a JSON string. The output will be indented. The replacer describes how the value should be transformed. It is a function which receives a key and a value. @@ -177,7 +177,7 @@ let json = ("someNumber", JSON.Encode.int(42)), ])->JSON.Encode.object -let replacer = (key, value) => { +let replacer = (_, value) => { let decodedValue = value->JSON.Decode.string switch decodedValue { @@ -188,10 +188,10 @@ let replacer = (key, value) => { JSON.stringifyWithReplacerAndIndent(json, replacer, 2) // { - "foo": "BAR", - "hello": "WORLD", - "someNumber": 42 -} +// "foo": "BAR", +// "hello": "WORLD", +// "someNumber": 42 +// } ``` */ @val @@ -321,7 +321,7 @@ BigInt.fromInt(0)->JSON.stringifyAny external stringifyAnyWithIndent: ('a, @as(json`null`) _, int) => option = "JSON.stringify" /** -`stringifyAnyWithReplacer(json, replacer)` +`stringifyAnyWithReplacer(json, replacer)` Converts any type to a JSON string. The replacer describes how the value should be transformed. It is a function which receives a key and a value. @@ -337,7 +337,7 @@ let dict = Dict.fromArray([ ("someNumber", JSON.Encode.int(42)), ]) -let replacer = (key, value) => { +let replacer = (_, value) => { let decodedValue = value->JSON.Decode.string switch decodedValue { @@ -382,7 +382,7 @@ let dict = Dict.fromArray([ ("someNumber", JSON.Encode.int(42)), ]) -let replacer = (key, value) => { +let replacer = (_, value) => { let decodedValue = value->JSON.Decode.string switch decodedValue { diff --git a/src/Core__List.resi b/src/Core__List.resi index 5733ad17..bb4acd25 100644 --- a/src/Core__List.resi +++ b/src/Core__List.resi @@ -645,15 +645,11 @@ zero for all `list1` and `list2`. ## Examples ```rescript -List.compare(list{3}, list{3, 7}, (a, b) => compare(a, b)) /* (-1.) */ - -List.compare(list{5, 3}, list{5}, (a, b) => compare(a, b)) /* 1. */ - -List.compare(list{1, 3, 5}, list{1, 4, 2}, (a, b) => compare(a, b)) /* (-1.) */ - -List.compare(list{1, 3, 5}, list{1, 2, 3}, (a, b) => compare(a, b)) /* 1. */ - -List.compare(list{1, 3, 5}, list{1, 3, 5}, (a, b) => compare(a, b)) /* 0. */ +List.compare(list{3}, list{3, 7}, (a, b) => Int.compare(a, b)) // -1. +List.compare(list{5, 3}, list{5}, (a, b) => Int.compare(a, b)) // 1. +List.compare(list{1, 3, 5}, list{1, 4, 2}, (a, b) => Int.compare(a, b)) // -1. +List.compare(list{1, 3, 5}, list{1, 2, 3}, (a, b) => Int.compare(a, b)) // 1. +List.compare(list{1, 3, 5}, list{1, 3, 5}, (a, b) => Int.compare(a, b)) // 0. ``` **Please note:** The total ordering of List is different from Array, diff --git a/src/Core__Map.resi b/src/Core__Map.resi index 643bcbdd..1f29caa5 100644 --- a/src/Core__Map.resi +++ b/src/Core__Map.resi @@ -89,10 +89,10 @@ Clears all entries in the map. let map = Map.make() map->Map.set("someKey", "someValue") -let size = map->Map.size // 1 +map->Map.size // 1 map->Map.clear -let size = map->Map.size // 0 +map->Map.size // 0 ``` */ @send diff --git a/src/Core__Math.resi b/src/Core__Math.resi index a9f39643..9dab2e78 100644 --- a/src/Core__Math.resi +++ b/src/Core__Math.resi @@ -51,7 +51,7 @@ module Constants: { ## Examples ```rescript - Math.Constants.LN2 + Math.Constants.ln2 ``` */ @val @@ -209,7 +209,7 @@ module Int: { ```rescript Math.Int.minMany([1, 2]) // 1 Math.Int.minMany([-1, -2]) // -2 - Math.Int.minMany([])->Float.isFinite // false + Math.Int.minMany([])->Int.toFloat->Float.isFinite // false ``` */ @variadic @@ -240,7 +240,7 @@ module Int: { ```rescript Math.Int.maxMany([1, 2]) // 2 Math.Int.maxMany([-1, -2]) // -1 - Math.Int.maxMany([])->Float.isFinite // false + Math.Int.maxMany([])->Int.toFloat->Float.isFinite // false ``` */ @variadic @@ -333,8 +333,8 @@ See [`Math.acos`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere ## Examples ```rescript -Math.acos(-1) // 3.141592653589793 -Math.acos(-3)->Float.isNaN // true +Math.acos(-1.0) // 3.141592653589793 +Math.acos(-3.0)->Float.isNaN // true ``` */ @val @@ -348,7 +348,7 @@ See [`Math.acosh`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ## Examples ```rescript -Math.acosh(1) // 0.0 +Math.acosh(1.0) // 0.0 Math.acosh(0.5)->Float.isNaN // true ``` */ @@ -377,8 +377,8 @@ See [`Math.asinh`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ## Examples ```rescript -Math.asinh(-1) // -0.881373587019543 -Math.asinh(-0) // -0.0 +Math.asinh(-1.0) // -0.881373587019543 +Math.asinh(-0.0) // -0.0 ``` */ @val @@ -393,7 +393,7 @@ See [`Math.atan`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refere ```rescript Math.atan(-0.0) // -0.0 Math.atan(0.0) // 0.0 -Math.atan(1) // 0.7853981633974483 +Math.atan(1.0) // 0.7853981633974483 ``` */ @val @@ -583,8 +583,8 @@ See [`Math.hypot`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer ## Examples ```rescript -Math.hypot([3.0, 4.0, 5.0]) // 7.0710678118654755 -Math.hypot([]) // 0.0 +Math.hypotMany([3.0, 4.0, 5.0]) // 7.0710678118654755 +Math.hypotMany([]) // 0.0 ``` */ @variadic diff --git a/src/Core__Null.resi b/src/Core__Null.resi index ffa7b5d5..af2cd4ee 100644 --- a/src/Core__Null.resi +++ b/src/Core__Null.resi @@ -74,7 +74,7 @@ Turns an `option` into a `Null.t`. `None` will be converted to `null`. ```rescript let optString: option = None let asNull = optString->Null.fromOption // Null.t -Console.log(asNull == null) // Logs `true` to the console. +Console.log(asNull == Null.null) // Logs `true` to the console. ``` */ let fromOption: option<'a> => t<'a> @@ -86,14 +86,14 @@ let fromOption: option<'a> => t<'a> ## Examples ```rescript -Null.getOr(null, "Banana") // Banana -Null.getOr(Nulalble.make("Apple"), "Banana") // Apple +Null.getOr(Null.null, "Banana") // Banana +Null.getOr(Null.make("Apple"), "Banana") // Apple let greet = (firstName: option) => - "Greetings " ++ firstName->Null.getOr("Anonymous") + "Greetings " ++ firstName->Option.getOr("Anonymous") -Null.make("Jane")->greet // "Greetings Jane" -null->greet // "Greetings Anonymous" +Null.make("Jane")->Null.toOption->greet // "Greetings Jane" +Null.null->Null.toOption->greet // "Greetings Anonymous" ``` */ let getOr: (t<'a>, 'a) => 'a @@ -106,7 +106,7 @@ let getWithDefault: (t<'a>, 'a) => 'a ```rescript Null.getExn(Null.make(3)) // 3 -Null.getExn(null) /* Raises an Error */ +Null.getExn(Null.null) /* Raises an Error */ ``` ## Exceptions @@ -122,7 +122,7 @@ let getExn: t<'a> => 'a ```rescript Null.getUnsafe(Null.make(3)) == 3 -Null.getUnsafe(null) // Raises an error +Null.getUnsafe(Null.null) // Raises an error ``` ## Important @@ -139,7 +139,7 @@ external getUnsafe: t<'a> => 'a = "%identity" ```rescript Null.forEach(Null.make("thing"), x => Console.log(x)) // logs "thing" -Null.forEach(null, x => Console.log(x)) // returns () +Null.forEach(Null.null, x => Console.log(x)) // logs nothing ``` */ let forEach: (t<'a>, 'a => unit) => unit @@ -152,7 +152,7 @@ let forEach: (t<'a>, 'a => unit) => unit ```rescript Null.map(Null.make(3), x => x * x) // Null.make(9) -Null.map(null, x => x * x) // null +Null.map(Null.null, x => x * x) // null ``` */ let map: (t<'a>, 'a => 'b) => t<'b> @@ -167,7 +167,7 @@ otherwise returns `default`. let someValue = Null.make(3) someValue->Null.mapOr(0, x => x + 5) // 8 -let noneValue = null +let noneValue = Null.null noneValue->Null.mapOr(0, x => x + 5) // 0 ``` */ @@ -187,12 +187,12 @@ let addIfAboveOne = value => if (value > 1) { Null.make(value + 1) } else { - null + Null.null } Null.flatMap(Null.make(2), addIfAboveOne) // Null.make(3) Null.flatMap(Null.make(-4), addIfAboveOne) // null -Null.flatMap(null, addIfAboveOne) // null +Null.flatMap(Null.null, addIfAboveOne) // null ``` */ let flatMap: (t<'a>, 'a => t<'b>) => t<'b> diff --git a/src/Core__Nullable.resi b/src/Core__Nullable.resi index 5b840b5f..c33f7c92 100644 --- a/src/Core__Nullable.resi +++ b/src/Core__Nullable.resi @@ -98,13 +98,13 @@ otherwise return `default`. ```rescript Nullable.getOr(Nullable.null, "Banana") // Banana -Nullable.getOr(Nulalble.make("Apple"), "Banana") // Apple +Nullable.getOr(Nullable.make("Apple"), "Banana") // Apple let greet = (firstName: option) => - "Greetings " ++ firstName->Nullable.getOr("Anonymous") + "Greetings " ++ firstName->Option.getOr("Anonymous") -Nullable.make("Jane")->greet // "Greetings Jane" -Nullable.null->greet // "Greetings Anonymous" +Nullable.make("Jane")->Nullable.toOption->greet // "Greetings Jane" +Nullable.null->Nullable.toOption->greet // "Greetings Anonymous" ``` */ let getOr: (t<'a>, 'a) => 'a diff --git a/src/Core__Object.res b/src/Core__Object.res index d4828efd..696f6760 100644 --- a/src/Core__Object.res +++ b/src/Core__Object.res @@ -165,9 +165,9 @@ external keysToArray: {..} => array = "Object.keys" ```rescript let point = {"x": 1, "y": 2} -{"a": 1}->hasOwnProperty("a") // true -{"a": 1}->hasOwnProperty("b") // false -{"a": 1}->hasOwnProperty("toString") // false +{"a": 1}->Object.hasOwnProperty("a") // true +{"a": 1}->Object.hasOwnProperty("b") // false +{"a": 1}->Object.hasOwnProperty("toString") // false ``` */ @val diff --git a/src/Core__Option.resi b/src/Core__Option.resi index 8d2d3d33..fbaceba4 100644 --- a/src/Core__Option.resi +++ b/src/Core__Option.resi @@ -173,7 +173,7 @@ let getWithDefault: (option<'a>, 'a) => 'a ```rescript Option.orElse(Some(1812), Some(1066)) == Some(1812) -Option.orElse(None, Some(1066) == Some(1066) +Option.orElse(None, Some(1066)) == Some(1066) Option.orElse(None, None) == None ``` */ @@ -241,16 +241,14 @@ the first argument is greater than the second. ## Examples ```rescript -let clockCompare = (a, b) => compare(mod(a, 12), mod(b, 12)) - -open Option - -compare(Some(3), Some(15), clockCompare) // 0. -compare(Some(3), Some(14), clockCompare) // 1. -compare(Some(2), Some(15), clockCompare) // (-1.) -compare(None, Some(15), clockCompare) // (-1.) -compare(Some(14), None, clockCompare) // 1. -compare(None, None, clockCompare) // 0. +let clockCompare = (a, b) => Int.compare(mod(a, 12), mod(b, 12)) + +Option.compare(Some(3), Some(15), clockCompare) // 0. +Option.compare(Some(3), Some(14), clockCompare) // 1. +Option.compare(Some(2), Some(15), clockCompare) // (-1.) +Option.compare(None, Some(15), clockCompare) // (-1.) +Option.compare(Some(14), None, clockCompare) // 1. +Option.compare(None, None, clockCompare) // 0. ``` */ let compare: (option<'a>, option<'b>, ('a, 'b) => Core__Ordering.t) => Core__Ordering.t diff --git a/src/Core__Promise.resi b/src/Core__Promise.resi index ec482ff9..2a366604 100644 --- a/src/Core__Promise.resi +++ b/src/Core__Promise.resi @@ -65,7 +65,7 @@ Promise.make((resolve, reject) => { ->then(str => { Console.log(str)->resolve }) -->catch(e => { +->catch(_ => { Console.log("Error occurred") resolve() }) @@ -127,7 +127,8 @@ See [`Promise.then`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Ref ## Examples ```rescript -Promise.resolve(5) +open Promise +resolve(5) ->then(num => { resolve(num + 5) }) @@ -149,6 +150,7 @@ within the provided callback (e.g. `thenResolve(value => resolve(value))`). ## Examples ```rescript +open Promise resolve("Anna") ->thenResolve(str => { "Hello " ++ str @@ -173,12 +175,13 @@ it originally received. See [`Promise.finally`](https://developer.mozilla.org/en ## Examples ```rescript +open Promise exception SomeError(string) let isDone = ref(false) resolve(5) ->then(_ => { - reject(TestError("test")) + reject(SomeError("test")) }) ->then(v => { Console.log2("final result", v) @@ -211,8 +214,8 @@ external finally: (t<'a>, unit => unit) => t<'a> = "finally" open Promise let racer = (ms, name) => { Promise.make((resolve, _) => { - Global.setTimeout(() => { - resolve(. name) + setTimeout(() => { + resolve(name) }, ms)->ignore }) } diff --git a/src/Core__Result.resi b/src/Core__Result.resi index 8d626053..a30c5e0b 100644 --- a/src/Core__Result.resi +++ b/src/Core__Result.resi @@ -57,16 +57,17 @@ let getExn: result<'a, 'b> => 'a /** - `mapOr(res, default, f)`: When res is `Ok(n)`, returns `f(n)`, - otherwise `default`. +`mapOr(res, default, f)`: When res is `Ok(n)`, returns `f(n)`, otherwise `default`. - ```res example - let ok = Result.Ok(42) - Result.mapOr(ok, 0, (x) => x / 2) == 21 +## Examples - let error = Result.Error("Invalid data") - Result.mapOr(error, 0, (x) => x / 2) == 0 - ``` +```rescript +let ok = Ok(42) +Result.mapOr(ok, 0, (x) => x / 2) == 21 + +let error = Error("Invalid data") +Result.mapOr(error, 0, (x) => x / 2) == 0 +``` */ let mapOr: (result<'a, 'c>, 'b, 'a => 'b) => 'b @@ -74,51 +75,56 @@ let mapOr: (result<'a, 'c>, 'b, 'a => 'b) => 'b let mapWithDefault: (result<'a, 'c>, 'b, 'a => 'b) => 'b /** - `map(res, f)`: When res is `Ok(n)`, returns `Ok(f(n))`. Otherwise returns res - unchanged. Function `f` takes a value of the same type as `n` and returns an - ordinary value. +`map(res, f)`: When res is `Ok(n)`, returns `Ok(f(n))`. Otherwise returns res +unchanged. Function `f` takes a value of the same type as `n` and returns an +ordinary value. - ```res example - let f = (x) => sqrt(Int.toFloat(x)) +## Examples - Result.map(Ok(64), f) == Ok(8.0) +```rescript +let f = (x) => sqrt(Int.toFloat(x)) - Result.map(Error("Invalid data"), f) == Error("Invalid data") - ``` +Result.map(Ok(64), f) == Ok(8.0) + +Result.map(Error("Invalid data"), f) == Error("Invalid data") +``` */ let map: (result<'a, 'c>, 'a => 'b) => result<'b, 'c> /** - `flatMap(res, f)`: When res is `Ok(n)`, returns `f(n)`. Otherwise, returns res - unchanged. Function `f` takes a value of the same type as `n` and returns a - `Result`. +`flatMap(res, f)`: When res is `Ok(n)`, returns `f(n)`. Otherwise, returns res +unchanged. Function `f` takes a value of the same type as `n` and returns a +`Result`. - ```res example - let recip = (x) => - if (x !== 0.0) { - Result.Ok(1.0 /. x) - } else { - Result.Error("Divide by zero") - } +## Examples - Result.flatMap(Ok(2.0), recip) == Ok(0.5) +```rescript +let recip = (x) => + if (x !== 0.0) { + Ok(1.0 /. x) + } else { + Error("Divide by zero") + } - Result.flatMap(Ok(0.0), recip) == Error("Divide by zero") +Result.flatMap(Ok(2.0), recip) == Ok(0.5) - Result.flatMap(Error("Already bad"), recip) == Error("Already bad") - ``` +Result.flatMap(Ok(0.0), recip) == Error("Divide by zero") + +Result.flatMap(Error("Already bad"), recip) == Error("Already bad") +``` */ let flatMap: (result<'a, 'c>, 'a => result<'b, 'c>) => result<'b, 'c> /** - `getOr(res, defaultValue)`: If `res` is `Ok(n)`, returns `n`, - otherwise `default` +`getOr(res, defaultValue)`: If `res` is `Ok(n)`, returns `n`, otherwise `default` - ```res example - Result.getOr(Ok(42), 0) == 42 +## Examples - Result.getOr(Error("Invalid Data"), 0) == 0 - ``` +```rescript +Result.getOr(Ok(42), 0) == 42 + +Result.getOr(Error("Invalid Data"), 0) == 0 +``` */ let getOr: (result<'a, 'b>, 'a) => 'a @@ -126,79 +132,81 @@ let getOr: (result<'a, 'b>, 'a) => 'a let getWithDefault: (result<'a, 'b>, 'a) => 'a /** - `isOk(res)`: Returns `true` if `res` is of the form `Ok(n)`, `false` if it is - the `Error(e)` variant. +`isOk(res)`: Returns `true` if `res` is of the form `Ok(n)`, `false` if it is the `Error(e)` variant. */ let isOk: result<'a, 'b> => bool /** - `isError(res)`: Returns `true` if `res` is of the form `Error(e)`, `false` if - it is the `Ok(n)` variant. +`isError(res)`: Returns `true` if `res` is of the form `Error(e)`, `false` if it is the `Ok(n)` variant. */ let isError: result<'a, 'b> => bool /** - `equal(res1, res2, f)`: Determine if two `Result` variables are equal with - respect to an equality function. If `res1` and `res2` are of the form `Ok(n)` - and `Ok(m)`, return the result of `f(n, m)`. If one of `res1` and `res2` are of - the form `Error(e)`, return false If both `res1` and `res2` are of the form - `Error(e)`, return true +`equal(res1, res2, f)`: Determine if two `Result` variables are equal with +respect to an equality function. If `res1` and `res2` are of the form `Ok(n)` +and `Ok(m)`, return the result of `f(n, m)`. If one of `res1` and `res2` are of +the form `Error(e)`, return false If both `res1` and `res2` are of the form +`Error(e)`, return true - ```res example - let good1 = Result.Ok(42) +## Examples + +```rescript +let good1 = Ok(42) - let good2 = Result.Ok(32) +let good2 = Ok(32) - let bad1 = Result.Error("invalid") +let bad1 = Error("invalid") - let bad2 = Result.Error("really invalid") +let bad2 = Error("really invalid") - let mod10equal = (a, b) => mod(a, 10) === mod(b, 10) +let mod10equal = (a, b) => mod(a, 10) === mod(b, 10) - Result.equal(good1, good2, mod10equal) == true +Result.equal(good1, good2, mod10equal) == true - Result.equal(good1, bad1, mod10equal) == false +Result.equal(good1, bad1, mod10equal) == false - Result.equal(bad2, good2, mod10equal) == false +Result.equal(bad2, good2, mod10equal) == false - Result.equal(bad1, bad2, mod10equal) == true - ``` +Result.equal(bad1, bad2, mod10equal) == true +``` */ let equal: (result<'a, 'c>, result<'b, 'd>, ('a, 'b) => bool) => bool /** - `compare(res1, res2, f)`: Compare two `Result` variables with respect to a - comparison function. The comparison function returns -1. if the first variable - is "less than" the second, 0. if the two variables are equal, and 1. if the first - is "greater than" the second. +`compare(res1, res2, f)`: Compare two `Result` variables with respect to a +comparison function. The comparison function returns -1. if the first variable +is "less than" the second, 0. if the two variables are equal, and 1. if the first +is "greater than" the second. - If `res1` and `res2` are of the form `Ok(n)` and `Ok(m)`, return the result of - `f(n, m)`. If `res1` is of the form `Error(e)` and `res2` of the form `Ok(n)`, - return -1. (nothing is less than something) If `res1` is of the form `Ok(n)` and - `res2` of the form `Error(e)`, return 1. (something is greater than nothing) If - both `res1` and `res2` are of the form `Error(e)`, return 0. (equal) +If `res1` and `res2` are of the form `Ok(n)` and `Ok(m)`, return the result of +`f(n, m)`. If `res1` is of the form `Error(e)` and `res2` of the form `Ok(n)`, +return -1. (nothing is less than something) If `res1` is of the form `Ok(n)` and +`res2` of the form `Error(e)`, return 1. (something is greater than nothing) If +both `res1` and `res2` are of the form `Error(e)`, return 0. (equal) - ```res example - let good1 = Result.Ok(59) +## Examples - let good2 = Result.Ok(37) +```rescript +let good1 = Ok(59) - let bad1 = Result.Error("invalid") +let good2 = Ok(37) - let bad2 = Result.Error("really invalid") +let bad1 = Error("invalid") - let mod10cmp = (a, b) => Pervasives.compare(mod(a, 10), mod(b, 10)) +let bad2 = Error("really invalid") - Result.compare(Ok(39), Ok(57), mod10cmp) == 1. +let mod10cmp = (a, b) => Int.compare(mod(a, 10), mod(b, 10)) - Result.compare(Ok(57), Ok(39), mod10cmp) == (-1.) +Result.compare(Ok(39), Ok(57), mod10cmp) == 1. - Result.compare(Ok(39), Error("y"), mod10cmp) == 1. +Result.compare(Ok(57), Ok(39), mod10cmp) == (-1.) - Result.compare(Error("x"), Ok(57), mod10cmp) == (-1.) +Result.compare(Ok(39), Error("y"), mod10cmp) == 1. - Result.compare(Error("x"), Error("y"), mod10cmp) == 0. - ``` +Result.compare(Error("x"), Ok(57), mod10cmp) == (-1.) + +Result.compare(Error("x"), Error("y"), mod10cmp) == 0. +``` */ let compare: (result<'a, 'c>, result<'b, 'd>, ('a, 'b) => Core__Ordering.t) => Core__Ordering.t @@ -221,8 +229,8 @@ let forEach: (result<'a, 'b>, 'a => unit) => unit ```rescript let format = n => `Error code: ${n->Int.toString}` -mapError(Error(14), format) // Error("Error code: 14") -mapError(Ok("abc"), format) // Ok("abc") +Result.mapError(Error(14), format) // Error("Error code: 14") +Result.mapError(Ok("abc"), format) // Ok("abc") ``` */ let mapError: (result<'a, 'b>, 'b => 'c) => result<'a, 'c> diff --git a/src/Core__Set.resi b/src/Core__Set.resi index 621dee0c..297755d0 100644 --- a/src/Core__Set.resi +++ b/src/Core__Set.resi @@ -90,10 +90,10 @@ Clears all entries in the set. let set = Set.make() set->Set.add("someKey") -let size = set->Set.size // 1 +set->Set.size // 1 set->Set.clear -let size = set->Set.size // 0 +set->Set.size // 0 ``` */ @send diff --git a/src/Core__String.resi b/src/Core__String.resi index c3cdce44..98b24971 100644 --- a/src/Core__String.resi +++ b/src/Core__String.resi @@ -68,7 +68,7 @@ See [`String.fromCharCode`](https://developer.mozilla.org/en-US/docs/Web/JavaScr ```rescript String.fromCharCodeMany([189, 43, 190, 61]) == "½+¾=" -String.fromCharCode([65, 66, 67]) == "ABC" +String.fromCharCodeMany([65, 66, 67]) == "ABC" ``` */ @variadic @@ -324,8 +324,8 @@ external indexOf: (string, string) => int = "indexOf" ## Examples ```rescript -String.indexOf("bookseller", "ok") == Some(2) -String.indexOf("bookseller", "xyz") == None +String.indexOfOpt("bookseller", "ok") == Some(2) +String.indexOfOpt("bookseller", "xyz") == None ``` */ let indexOfOpt: (string, string) => option @@ -374,9 +374,9 @@ external lastIndexOf: (string, string) => int = "lastIndexOf" ## Examples ```rescript -String.lastIndexOf("bookseller", "ok") == Some(2) -String.lastIndexOf("beekeeper", "ee") == Some(4) -String.lastIndexOf("abcdefg", "xyz") == None +String.lastIndexOfOpt("bookseller", "ok") == Some(2) +String.lastIndexOfOpt("beekeeper", "ee") == Some(4) +String.lastIndexOfOpt("abcdefg", "xyz") == None ``` */ let lastIndexOfOpt: (string, string) => option @@ -440,8 +440,8 @@ let string1 = "\uFB00" let string2 = "\u0066\u0066" Console.log(string1 === string2) // false -let normalizeString1 = String.normalize(string1, "NFKD") -let normalizeString2 = String.normalize(string2, "NFKD") +let normalizeString1 = String.normalize(string1) +let normalizeString2 = String.normalize(string2) assert(normalizeString1 === normalizeString2) ``` */ @@ -571,7 +571,7 @@ See [`String.replace`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ```rescript let str = "beautiful vowels" let re = %re("/[aeiou]/g") -let matchFn = (matchPart, _offset, _wholeString) => String.toUpperCase(matchPart) +let matchFn = (~match, ~offset as _, ~input as _) => String.toUpperCase(match) String.unsafeReplaceRegExpBy0(str, re, matchFn) == "bEAUtIfUl vOwEls" ``` */ @@ -592,8 +592,8 @@ See [`String.replace`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ```rescript let str = "Jony is 40" let re = %re("/(Jony is )\d+/g") -let matchFn = (_match, part1, _offset, _wholeString) => { - part1 ++ "41" +let matchFn = (~match as _, ~group1, ~offset as _, ~input as _) => { + group1 ++ "41" } String.unsafeReplaceRegExpBy1(str, re, matchFn) == "Jony is 41" ``` @@ -615,8 +615,8 @@ See [`String.replace`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ```rescript let str = "7 times 6" let re = %re("/(\d+) times (\d+)/") -let matchFn = (_match, p1, p2, _offset, _wholeString) => { - switch (Int.fromString(p1), Int.fromString(p2)) { +let matchFn = (~match as _, ~group1, ~group2, ~offset as _, ~input as _) => { + switch (Int.fromString(group1), Int.fromString(group2)) { | (Some(x), Some(y)) => Int.toString(x * y) | _ => "???" } @@ -671,8 +671,8 @@ external search: (string, Core__RegExp.t) => int = "search" ## Examples ```rescript -String.search("testing 1 2 3", %re("/\d+/")) == Some(8) -String.search("no numbers", %re("/\d+/")) == None +String.searchOpt("testing 1 2 3", %re("/\d+/")) == Some(8) +String.searchOpt("no numbers", %re("/\d+/")) == None ``` */ let searchOpt: (string, Core__RegExp.t) => option @@ -743,9 +743,9 @@ the array will contain all the substrings. ## Examples ```rescript -String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=3) = ["ant", "bee", "cat"] -String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=0) = [] -String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=9) = ["ant", "bee", "cat", "dog", "elk"] +String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=3) == ["ant", "bee", "cat"] +String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=0) == [] +String.splitAtMost("ant/bee/cat/dog/elk", "/", ~limit=9) == ["ant", "bee", "cat", "dog", "elk"] ``` */ @send