Walkthrough: live
Source walkthrough from src-doc/walkthrough/std_lang_02_live.clj
This page promotes the existing walkthrough source into the public Hara docs. The implementation source remains in src-doc/walkthrough/std_lang_02_live.clj; this page explains the intent and links it to the surrounding Hara layers.
1 Motivation
The walkthrough shows how hara.lang scripts define target contexts, how forms are emitted or executed, and how generated pointers connect Clojure authoring to target language code.
2 How to use it
Read the source file directly for the executable facts. The docs page keeps high-level explanation here and uses selected fact snippets below.
What each section demonstrates: the first shows !.js returning values instead of code strings; the second makes the emission visible with l/with:print-all; the third shows the identical hara.lang body running under Lua and Python; the last mixes live results from all three runtimes in one Clojure expression.
3 Walkthrough
3.1 Live JS execution
Adding :runtime :basic to l/script- makes !.js execute the generated code and return the result. You can define functions and call them like ordinary Clojure values.
evaluate JS arithmetic live
^{:refer hara.lang/script- :added "4.0"}
(do
(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(!.js (+ 1 2 3)))
=> 6
define and call a JS function
^{:refer hara.lang/emit-ptr :added "4.0"}
(do
(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.js hello []
(return (+ 1 2 3)))
[(hello)
(!.js (+ (-/hello) (-/hello)))])
=> [6 12]
3.2 Observing emitted code
l/with:print-all echoes the generated code that is sent to the runtime. Wrap it in with-out-str to capture the output as a string.
capture emitted JS with print-all
^{:refer hara.lang/with:print-all :added "4.0"}
(do
(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.js hello []
(return (+ 1 2 3)))
(string?
(with-out-str
(l/with:print-all
(!.js (+ (-/hello) (-/hello)))))))
=> true
3.3 Live Lua and Python execution
The :basic runtime works for Lua and Python too. The same hara.lang function body runs in each target process.
evaluate Lua live
^{:refer hara.lang/script- :added "4.0"}
(do
(l/script- :lua
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.lua world []
(return (+ 1 2 3)))
(world))
=> 6
evaluate Python live
^{:refer hara.lang/script- :added "4.0"}
(do
(l/script- :python
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.py again []
(return (+ 1 2 3)))
(again))
=> 6
3.4 End-to-end: combine live results
Because each runtime returns Clojure values, you can mix results from several languages in a single Clojure expression.
sum results from live JS, Lua, and Python runtimes
(do
(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.js hello []
(return 1))
(l/script- :lua
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.lua world []
(return 2))
(l/script- :python
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
(defn.py again []
(return 3))
(+ (hello) (world) (again)))
=> 6
4 Source
(l/script- :js
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
js runtime
^:hidden
(!.js
(+ 1 2 3))
=> 6
(defn.js hello
[]
(return
(+ 1 2 3)))
(hello)
=> 6
(!.js (+ (-/hello)
(-/hello)))
=> 12
;;
;; print out what was sent to the repl
;;
(std.concurrent.print/with-out-str
(l/with:print-all
(!.js (+ (-/hello)
(-/hello)))))
=> string?
;;
;; `^*` is shortcut for print-all
;;
(std.concurrent.print/with-out-str
^*(!.js (+ (-/hello)
(-/hello))))
=> string?
(l/script- :lua
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
lua runtime
^:hidden
(!.lua
(+ 1 2 3))
=> 6
(defn.lua world
[]
(return
(+ 1 2 3)))
(world)
=> 6
(!.lua (+ (-/world)
(-/world)))
=> 12
(std.concurrent.print/with-out-str
(l/with:print-all
(!.lua (+ (-/world)
(-/world)))))
=> string?
(l/script- :python
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
python runtime
^:hidden
(!.py
(+ 1 2 3))
=> 6
(defn.py again
[]
(return
(+ 1 2 3)))
(again)
=> 6
(!.py (+ (-/again)
(-/again)))
=> 12
(std.concurrent.print/with-out-str
(l/with:print-all
(!.py (+ (-/again)
(-/again)))))
=> string?
(l/script- :r
{:runtime :basic
:require [[xt.lang.spec-base :as xt]]})
r runtime
^:hidden
(!.R
(+ 1 2 3))
=> 6
(def.R stuff
(fn []
(return
(+ 1 2 3))))
(stuff)
=> 6
(!.R (+ (-/stuff)
(-/stuff)))
=> 12
(std.concurrent.print/with-out-str
(l/with:print-all
(!.R (+ (-/stuff)
(-/stuff)))))
=> string?
Altogether now
^:hidden
;;
;; execution on all 4 runtimes, then combining result with clojure
;;
(+ (-/hello)
(-/world)
(-/again)
(-/stuff))
=> 24