(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]
[xt.lang.common-lib :as k]
[xt.lang.common-string :as xts]]})
(fact:global
{:setup [(l/rt:restart)]
:teardown [(l/rt:stop)]})
xt.lang
Portable language primitives and common libraries.
xt.lang defines reusable xtalk libraries that target JS, Lua, Python, Dart, and other runtimes through hara.lang emission.
1 Motivation
Target languages differ in collection APIs, nil handling, string operations, promises, modules, and resource access. xt.lang gives generated programs one shared vocabulary for those behaviors.
2 How to use it
A hara script requires the libraries it needs, then emitted xtalk code calls those portable helpers. Application examples in src-build/play/*xtalk* and tests under test-lang/xt/lang show this pattern.
(l/script :xtalk
{:require [[xt.lang.spec-base :as xt]
[xt.lang.common-data :as data]
[xt.lang.common-string :as string]]})
3 Walkthrough
3.1 Portable iteration
xt.lang.spec-base provides loop forms that expand to idiomatic loops on each target: for:array, for:object, and for:index.
iterate arrays and objects portably
^{:refer xt.lang.spec-base/for:array :added "4.0"}
(!.js
(var out [])
(xt/for:array [e [1 2 3 4]]
(when (> e 3)
(break))
(xt/x:arr-push out e))
out)
=> [1 2 3]
^{:refer xt.lang.spec-base/for:object :added "4.0"}
(!.js
(var out [])
(xt/for:object [[k v] {:a 1 :b 2}]
(xt/x:arr-push out [k v]))
out)
=> (just [["a" 1] ["b" 2]] :in-any-order)
3.2 Type predicates
xt.lang.common-lib exposes portable type checks so emitted code behaves consistently even when target truthiness differs.
check object type
^{:refer xt.lang.common-lib/is-object? :added "4.0"}
(!.js
[(k/is-object? {:a 1})
(k/is-object? [1 2 3])])
=> [true false]
^{:refer xt.lang.common-lib/is-string? :added "4.0"}
(!.js
[(k/is-string? "hello")
(k/is-string? 1)])
=> [true false]
^{:refer xt.lang.common-lib/is-array? :added "4.0"}
(!.js
[(k/is-array? [1 2 3])
(k/is-array? {:a 1})])
=> [true false]
3.3 String helpers
xt.lang.common-string provides portable split, join, replace, and symbol-path helpers.
split, join, and inspect symbol paths
^{:refer xt.lang.common-string/split :added "4.0"}
(!.js
(xts/split "hello/world" "/"))
=> ["hello" "world"]
^{:refer xt.lang.common-string/join :added "4.0"}
(!.js
(xts/join "/" ["hello" "world"]))
=> "hello/world"
^{:refer xt.lang.common-string/sym-pair :added "4.0"}
(!.js
(xts/sym-pair "xt.lang/common-string"))
=> ["xt.lang" "common-string"]
3.4 End-to-end: a tiny word counter
Combining loops and string helpers gives a portable word count that runs the same in every target runtime.
count words in a sentence
^{:refer xt.lang.common-string/split :added "4.0"}
(!.js
(var words (xts/split "hello portable world" " "))
(var count 0)
(xt/for:array [w words]
(:= count (+ count 1)))
count)
=> 3
4 Internal usage
The common libraries are used by xt.db, xt.event, xt.net, xt.substrate, and by generated single-source examples. The test-lang/xtbench tests exercise cross-target parity for these helpers.
5 API
6 xt.lang.base-lib Recommendations
xt.lang.base-lib provides a solid foundation for cross-language development. Here are some recommendations for new functionality that could make it even more useful:
- More Collection Functions:n
map,filter,reduce: These are fundamental higher-order functions for working with collections. Adding them toxt.lang.base-libwould make it much easier to write functional-style code in a cross-language way.nsort,sort-by: For sorting collections.ngroup-by: For grouping elements of a collection based on a key.n More String Functions:ntrim,trim-left,trim-right: For removing whitespace from strings.npad-left,pad-right: For padding strings to a certain length.nreplace: For replacing substrings.n Date/Time Functions:nnow: Returns the current time as a timestamp or a date object.nformat-date: Formats a date object into a string.nparse-date: Parses a string into a date object.n URL Functions:nurl-encode,url-decode: For encoding and decoding URL components.nparse-url: For parsing a URL into its components (protocol, host, path, etc.).n Randomness:nrand-int: Generates a random integer within a given range.nrand-nth: Returns a random element from a collection.nshuffle: Shuffles the elements of a collection.
7 xt.lang and xtalk Summary
The xt.lang namespace and the xtalk mechanism are at the heart of the foundation-base cross-language interoperability story. xtalk (cross-talk) is a system that allows code written in one language to call code written in another language, with automatic type conversion and marshalling.
Core Concepts:
xtalk:xtalkis a protocol and a set of conventions for defining and calling functions across different languages.nxt.lang.base-lib: This namespace provides a set of common utility functions that are designed to be used in a cross-language context. These functions have implementations in all the languages supported byfoundation-base.n Language-Specific Implementations: Each language supported byfoundation-basehas its own implementation of thextalkprotocol and thext.lang.base-libfunctions. For example,xt.lang.model.spec-jsandxt.lang.model.spec-luaprovide the JavaScript and Lua implementations, respectively.
How xtalk Works:
- Function Definition: When you define a function using
defn.xt, it is registered with thextalksystem.n2. Function Call: When you call anxtalkfunction from a different language, thextalksystem intercepts the call and performs the following steps:n Type Conversion: The arguments are converted from the source language's data types to a commonxtalkrepresentation.n Function Invocation: The target function is invoked with the converted arguments.n * Return Value Conversion: The return value is converted from the target language's data type back to the source language's data type.
xt.lang.base-lib:
The xt.lang.base-lib namespace provides a set of common utility functions that are essential for writing cross-language code. These functions include:
- Type Predicates:
is-string?,is-number?,is-boolean?,is-function?,is-object?,is-array?n Collection Functions:get-key,set-key,get-path,obj-keys,obj-vals,arr-clone,arr-slicen String Functions:str-len,str-char,str-split,str-joinn* Math Functions:m-abs,m-max,m-min,m-pow
Example: Using xtalk
xt.lang and xtalk Summary example
;; In a Clojure file
(ns my-clojure-ns
(:require [xt.lang :as l]))
(l/script :xtalk
{:require [[xt.lang.base-lib :as k]]})
(l/defn.xt my-clj-fn [s]
(k/to-uppercase s))
;; In a JavaScript file
(ns my-js-ns
(:require [xt.lang :as l]))
(l/script :js
{:require [[my-clojure-ns :as clj]]})
(l/defn.js my-js-fn []
(console.log (clj/my-clj-fn "hello")))
In this example, the my-js-fn function in JavaScript calls the my-clj-fn function in Clojure. The xtalk system automatically handles the conversion of the string argument and the return value between JavaScript and Clojure.
xtalk is a powerful mechanism that makes it easy to write polyglot applications with foundation-base. By providing a common set of utility functions and a seamless way to call functions across languages, xtalk greatly simplifies the process of building complex, multi-language systems.