{"id":21570063,"url":"https://github.com/lucifer1004/jlbun","last_synced_at":"2025-05-08T00:26:37.088Z","repository":{"id":65250332,"uuid":"582156503","full_name":"lucifer1004/jlbun","owner":"lucifer1004","description":"Using Julia in Bun!","archived":false,"fork":false,"pushed_at":"2024-11-27T04:47:20.000Z","size":497,"stargazers_count":62,"open_issues_count":12,"forks_count":1,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-12-19T03:11:15.493Z","etag":null,"topics":["bun","ffi","javascript","julia","typescript"],"latest_commit_sha":null,"homepage":"https://lucifer1004.github.io/jlbun","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lucifer1004.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-25T22:54:27.000Z","updated_at":"2024-05-29T16:21:20.000Z","dependencies_parsed_at":"2024-12-19T03:11:15.396Z","dependency_job_id":"62632402-9fda-403f-a0c2-767df4ac848e","html_url":"https://github.com/lucifer1004/jlbun","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucifer1004%2Fjlbun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucifer1004%2Fjlbun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucifer1004%2Fjlbun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lucifer1004%2Fjlbun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lucifer1004","download_url":"https://codeload.github.com/lucifer1004/jlbun/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231468021,"owners_count":18381174,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bun","ffi","javascript","julia","typescript"],"created_at":"2024-11-24T11:11:35.518Z","updated_at":"2024-12-27T10:08:01.510Z","avatar_url":"https://github.com/lucifer1004.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jlbun - Using Julia in Bun\n\n![Logo of jlbun](https://user-images.githubusercontent.com/13583761/210193825-4b898ddf-b4b2-4e21-a691-c05240bb81e3.png)\n\n- [jlbun - Using Julia in Bun](#jlbun---using-julia-in-bun)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Evaluate Julia code](#evaluate-julia-code)\n    - [Pass a Bun array to Julia](#pass-a-bun-array-to-julia)\n    - [Pass a Julia Array to Bun](#pass-a-julia-array-to-bun)\n    - [Do some linear algebra](#do-some-linear-algebra)\n    - [Install and use new packages](#install-and-use-new-packages)\n    - [Function calls with keyword arguments](#function-calls-with-keyword-arguments)\n    - [Call JS functions from Julia](#call-js-functions-from-julia)\n    - [Run Julia with multiple threads](#run-julia-with-multiple-threads)\n  - [Star History](#star-history)\n\n## Installation\n\n\u003e - You need to have `Bun`, `CMake` and `Julia` installed to use this library.\n\u003e - `bun install` does not run the packages's `install` scripts, so `npm install` is used instead. \n\n```bash\nnpm install jlbun\n```\n\n## Usage\n\n### Evaluate Julia code\n\n`jlbun` provides `Julia.eval()` and `Julia.tagEval()`. The former accepts a string, while the latter accepts a tagged template literal.\n\n```typescript\nimport { Julia } from \"jlbun\";\n\nJulia.init();\n\nJulia.eval('println(\"Hello from Julia\")'); // \"Hello from Julia\"\n\nconst arr = [1, 2, \"hello\"];\nJulia.tagEval`println(${arr})`; // \"Any[1, 2, \"hello\"]\"\n\nconst arr2 = new Uint8Array([1, 2, 3]);\nJulia.tagEval`println(${arr2})`; // \"UInt8[0x01, 0x02, 0x03]\"\n\nconst obj = { foo: 0, bar: false, bal: [1, 2, 3] }\nJulia.tagEval`println(${obj})`; // \"(foo = 0, bar = false, bal = Any[1, 2, 3])\"\n\nJulia.close();\n```\n\n### Pass a Bun array to Julia\n\n```typescript\nimport { Julia, JuliaArray } from \"jlbun\";\n\n// This initializes Julia and loads prelude symbols.\nJulia.init();\n\n// Create a `TypedArray` at the Bun side.\nconst bunArray = new Float64Array([1, 2, 3, 4, 5]);\n\n// Create a `JuliaArray` from the `TypedArray`.\nconst juliaArray = JuliaArray.from(bunArray);\n\n// These two arrays now share the same memory.\nJulia.Base.println(juliaArray); // [1.0, 2.0, 3.0, 4.0, 5.0]\n\n// We can modify the array at the Bun side (0-indexed).\nbunArray[1] = 100.0;\nJulia.Base.println(juliaArray); // [1.0, 100.0, 3.0, 4.0, 5.0]\n\n// Or we can modify the array at the Julia side (also 0-indexed).\njuliaArray.set(0, -10.0);\nJulia.Base.println(juliaArray); // [-10.0, 100.0, 3.0, 4.0, 5.0]\n\n// This cleans up Julia-related stuff.\nJulia.close();\n```\n\n### Pass a Julia Array to Bun\n\n```typescript\nimport { Julia } from \"jlbun\";\n\nJulia.init();\n\nconst juliaArray = Julia.Base.rand(10, 10);\nconst bunArray = juliaArray.rawValue;\nconsole.log(bunArray);\n\nJulia.close();\n```\n\n### Do some linear algebra\n\n```typescript\nimport { Julia } from \"jlbun\";\n\nJulia.init();\n\nconst juliaArray = Julia.Base.rand(2, 2);\nconst inv = Julia.Base.inv(juliaArray);\nconsole.log(inv.value);\n\nconst anotherJuliaArray = Julia.Base.rand(2, 2);\nconst product = Julia.Base[\"*\"](juliaArray, anotherJuliaArray);\nconsole.log(product.value);\n\n// We can also import Julia modules.\nconst LA = Julia.import(\"LinearAlgebra\");\nconsole.log(LA.norm(product).value);\n\nJulia.close();\n```\n\n### Install and use new packages\n\n```typescript\nimport { Julia } from \"jlbun\";\nimport { join } from \"path\";\n\nJulia.init();\n\n// Install `CairoMakie`\nJulia.Pkg.add(\"CairoMakie\");\n\n// Import `CairoMakie`\nconst Cairo = Julia.import(\"CairoMakie\");\n\n// Plot and save\nconst plt = Cairo.plot(Julia.Base.rand(10), Julia.Base.rand(10));\nCairo.save(join(process.cwd(), \"plot.png\"), plt);\n\nJulia.close();\n```\n\n### Function calls with keyword arguments\n\n```typescript\nimport { Julia, JuliaArray } from \"jlbun\";\n\nJulia.init();\n\nconst rawArray = new Int32Array([1, 10, 20, 30, 100]);\nconst arr = JuliaArray.from(rawArray);\nJulia.Base[\"sort!\"].callWithKwargs({ by: Julia.Base.string, rev: true }, arr);\nconsole.log(rawArray); // Int32Array(5) [ 30, 20, 100, 10, 1 ]\n\nJulia.close();\n```\n\n### Call JS functions from Julia\n\n```typescript\nimport { Julia, JuliaArray, JuliaFunction } from \"jlbun\";\n\nJulia.init();\n\nconst jsFunc = (x: number) =\u003e -x;\n\nconst cb = JuliaFunction.from(jsFunc, {\n  returns: \"i32\",\n  args: [\"i32\"],\n});\n\nconst arr = JuliaArray.from(new Int32Array([1, 10, 20, 30, 100]));\nconst neg = arr.map(cb);\nJulia.println(neg); // Int32[-1, -10, -20, -30, -100]\ncb.close();\n\nJulia.close();\n```\n\nTo deal with strings requires some tricks, see the example below:\n\n```typescript\nimport { Julia, JuliaArray, JuliaFunction, safeCString } from \"jlbun\";\n\nJulia.init();\n\nconst jsFunc = (x: number) =\u003e {\n  return safeCString(x.toString());\n};\n\nconst cb = JuliaFunction.from(jsFunc, {\n  returns: \"cstring\",\n  args: [\"i32\"],\n});\n\nconst arr = JuliaArray.from(new Int32Array([1, 10, 20, 30, 100]));\nJulia.Base[\"sort!\"].callWithKwargs({ by: cb, rev: true }, arr);\nJulia.println(arr); // Int32[30, 20, 100, 10, 1]\ncb.close();\n\nJulia.close();\n```\n\n### Run Julia with multiple threads\n\nTo use multiple threads in Julia, you need to set the `JULIA_NUM_THREADS` environment variable.\n\nWith `export JULIA_NUM_THREADS=2` set, the following program should output `2` instead of `1`:\n\n```typescript\nimport { Julia } from \"jlbun\";\n\nJulia.init();\n\nJulia.eval(\"println(Threads.nthreads())\");\n\nJulia.close();\n```\n\nA more advanced example:\n\n```typescript\nimport { Julia, JuliaFunction, JuliaTask, JuliaValue } from \"jlbun\";\n\nJulia.init();\n\nconst promises: Promise\u003cJuliaValue\u003e[] = [];\n\nconst func = Julia.eval(`function ()\n  ans = 0;\n  for i in 1:1000\n    ans += i\n  end\n  ans\nend\n`) as JuliaFunction;\n\nfor (let i = 0; i \u003c Julia.nthreads; i++) {\n  promises.push(JuliaTask.from(func).schedule(i).value);\n}\n\nconst results = (await Promise.all(promises)).map(promise =\u003e promise.value);\nconsole.log(results); // [ 500500n, 500500n, 500500n, 500500n, 500500n, 500500n, 500500n, 500500n ]\n\nJulia.close();\n```\n\n## Star History\n\n[![Star History Chart](https://api.star-history.com/svg?repos=lucifer1004/jlbun\u0026type=Date)](https://star-history.com/#lucifer1004/jlbun\u0026Date)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucifer1004%2Fjlbun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flucifer1004%2Fjlbun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flucifer1004%2Fjlbun/lists"}