hara.model
Target language specifications and xtalk function libraries.
hara.model contains target specs for JS, Lua, Python, Go, Dart, SQL, Solidity, xtalk, and annex languages. These models are the bridge between structured hara.lang forms and emitted target code.
1 Motivation
A language model owns target syntax, helper functions, type declarations, and runtime-specific emission rules. Generated projects in src-build/play use these models when producing Go, TypeScript, Lua, C, and JS artifacts.
2 API
3 Walkthrough
3.1 Emitting code to a target
hara.lang/emit-as is the main entry point for turning a hara form into target source code. The same expression can be rendered for different language models just by changing the target keyword.
arithmetic emits to multiple targets
(l/emit-as :js '[(+ 1 2)])
=> "1 + 2"
(l/emit-as :lua '[(+ 1 2)])
=> "1 + 2"
(l/emit-as :python '[(+ 1 2)])
=> "1 + 2"
3.2 Data literals
Maps and vectors are lowered into each target's native data syntax. The JS model uses JSON-like object notation, Lua uses table syntax, and Python uses dict/list literals.
maps and vectors render in target syntax
(l/emit-as :js '[{:a 1 :b 2}])
=> "{\"a\":1,\"b\":2}"
(l/emit-as :lua '[{:a 1 :b 2}])
=> "{a=1,b=2}"
(l/emit-as :js '[[1 2 3]])
=> "[1,2,3]"
(l/emit-as :lua '[[1 2 3]])
=> "setmetatable({1,2,3}, cjson.array_mt)"
3.3 Functions and control flow
Function definitions and conditionals are expanded into the target language's statements. The body is emitted with the target's block and return conventions.
define functions in JS and Lua
(l/emit-as :js '[(defn add [a b] (return (+ a b)))])
=> "function add(a,b){\n return a + b;\n}"
(l/emit-as :lua '[(defn add [a b] (return (+ a b)))])
=> "local function add(a,b)\n return a + b\nend"
if/else becomes target conditionals
(l/emit-as :js '[(if (> x 0) (return x) (return 0))])
=> "if(x > 0){\n return x;\n}\nelse{\n return 0;\n}"
(l/emit-as :lua '[(if (> x 0) (return x) (return 0))])
=> "if x > 0 then\n return x\nelse\n return 0\nend"
3.4 Target-specific helpers
Each model exposes small helper functions for target-specific edge cases. The JS model has js-regex and js-map-key; the Lua model has lua-map-key.
JS helpers
(js/js-regex #"abc")
=> "/abc/"
(js/js-map-key :hello js/+grammar+ {})
=> "\"hello\""
(js/js-map-key 'x js/+grammar+ {})
=> "[x]"
Lua helpers
(lua/lua-map-key :abc lua/+grammar+ {})
=> "abc"
(lua/lua-map-key 123 lua/+grammar+ {})
=> "[123]"
4 Xtalk Management Guide
xtalk (cross-talk) is a polymorphic template language that transpiles lisp to multiple runtime targets (JavaScript, Lua, Python, R, Ruby, Dart, Go, and others). The xtalk management system provides auditing, scaffolding, and maintenance tools for tracking language support, test coverage, and runtime compatibility across the codebase.
4.1 Core Concepts
4.1.1 Xtalk Model Layers
The xtalk system is organized into distinct layers:
4.1.2 Key Concepts
- Function Model (
fn_<lang>.clj): Defines how xtalk functions transpile to a specific languagen- Component Model (com_<lang>.clj): Defines xtalk data structure transpilation (records, dicts, etc.)n- Support Matrix: A semantic grid tracking which xtalk features (operators, constructs) are implemented vs. abstract vs. missing for each languagen- Inventory: Cataloging of model definitions, test coverage, and runtime availability
4.2 Common Tasks
4.2.1 1. Status and Inventory
Get overall xtalk status
lein manage status :with xtalk
From REPL:
(require '[code.manage.xtalk :as manage])\n\n;; Get model file inventory by language\n(manage/xtalk-model-inventory)\n;; => {:js {:model-files [...], :model-forms #{:fn :com}, :model-count 2}\n;; :lua {:model-files [...], ...}\n;; :python {...}}\n\n;; Get test coverage by language\n(manage/xtalk-test-inventory)\n;; => {:js {:test-files [...], :test-forms #{:fn :com}, :test-count 2}\n;; ...}\n\n;; Get runtime installation and spec support\n(manage/xtalk-runtime-inventory)\n;; => {:js {:runtime-installed? true, :runtime-executable? true, \n;; :spec-implemented 42, :spec-abstract 3, :spec-missing 0}\n;; :lua {:runtime-installed? false, ...}\n;; :python {...}}\n\n;; Get spec implementation status\n(manage/xtalk-spec-inventory)\n;; => {:js {:spec-tracked? true, :spec-feature-count 15,\n;; :spec-implemented 12, :spec-abstract 2, :spec-missing 1}\n;; ...}\n\n;; Unified language status (model + runtime + spec + test)\n(manage/xtalk-language-status)\n;; => {:js {:model-count 2, :test-count 2, :coverage 1.0,\n;; :runtime-installed? true, :spec-implemented 42, ...}\n;; ...}
4.2.2 2. Spec and Feature Auditing
Audit xtalk feature support across languages
# Full audit of all supported languages\nlein manage audit-languages\n\n# View feature status matrix\nlein manage support-matrix
From REPL:
;; Get list of xtalk categories (feature groups)\n(manage/xtalk-categories)\n;; => [:xtalk-conditional :xtalk-loop :xtalk-error ...]\n\n;; Get all xtalk operations\n(manage/xtalk-op-map)\n;; => {:x:if {...}, :x:do {...}, :x:try {...}, ...}\n\n;; Get all x:* symbols (xtalk operators)\n(manage/xtalk-symbols)\n;; => [:x:if :x:do :x:try :x:throw :x:let ...]\n\n;; Check feature implementation for specific language\n(manage/feature-status :js :x:if)\n;; => :implemented\n\n(manage/feature-status :lua :x:async)\n;; => :missing\n\n;; Get full support matrix (all languages + features)\n(manage/support-matrix)\n;; => {:languages [:js :lua :python :r :ruby]\n;; :features [:x:if :x:do :x:try ...]\n;; :status {:js {...}, :lua {...}, ...}\n;; :summary {:js {:implemented 40, :abstract 2, :missing 1}, ...}}\n\n;; Get support matrix for specific languages\n(manage/support-matrix [:js :python])\n\n;; Get support matrix for specific features\n(manage/support-matrix nil [:x:if :x:do :x:let])\n\n;; Audit installed language runtimes\n(manage/installed-languages)\n;; => [:js :lua :python :r]\n\n;; Find what's missing for each language\n(manage/missing-by-language)\n;; => {:lua [...], :python [...], :r [...]}\n\n;; Find which languages are missing specific features\n(manage/missing-by-feature)\n;; => {:x:async [:lua :r], :x:spread [:python], ...}
4.2.3 3. Xtalk Operations Inventory
Manage and document xtalk operator definitions
;; Generate operation inventory (reads grammar-xtalk)\n(manage/generate-xtalk-ops)\n;; Generates config/xtalk/xtalk_ops.edn with all operator details\n\n;; The result includes:\n;; {:op :x:if\n;; :category :xtalk-conditional\n;; :canonical-symbol hara.lang.base.grammar-xtalk/x:if\n;; :symbols [x:if]\n;; :macro hara.lang.base.grammar-xtalk/x:if\n;; :doc \"Conditional expression\"\n;; :cases [...]}
4.2.4 4. Test Scaffolding and Generation
Generate missing tests for grammar operations
# Scaffold grammar tests from operations inventory\nlein manage scaffold-xtalk-grammar-tests
From REPL:
;; Scaffold grammar operation tests\n(manage/scaffold-xtalk-grammar-tests {:write true})\n;; Generates test/std/lang/base/grammar_xtalk_ops_test.clj\n\n;; Split grammar tests by runtime language\n(manage/separate-runtime-tests {:lang :js :write true})\n;; Generates: test/std/lang/base/grammar_xtalk_js_test.clj
4.2.5 5. Language Support and Diagnostics
Check which language runtimes are installed and available
;; Get installed language runtimes\n(manage/installed-languages)\n;; => [:js :lua :python]\n\n;; Get languages that use xtalk as parent grammar\n(manage/audit-languages)\n;; => [:js :lua :python :r :rb :dart]\n\n;; Filter to only installed languages with xtalk parent\n(manage/audit-languages [:js :python :go])\n;; => [:js :python] (go removed if not installed)\n\n;; Visualize support matrix\n(manage/visualize-support)\n;; Formatted ASCII table showing language vs. feature support
4.2.6 6. Code Generation and Operations
Generate xtalk operator implementations
;; Generate default implementations for missing operators\n(manage/generate-xtalk-ops {:write true})\n;; Creates/updates operator configuration\n\n;; List all management operations\n(manage/xtalk-op-map)\n;; => All available management commands and their details
4.3 Workflow Examples
4.3.1 Workflow 1: Add Support for a New Language
Steps to add a new target language (e.g., Go):
- Create grammar specificationn - Add
:goto runtime languages insrc/std/lang/manage/xtalk_scaffold.cljn - Define+runtime-lang-config+entry for Gonn2. Create function modeln - Createsrc/std/lang/model/spec_xtalk/fn_go.cljn - Define how xtalk functions transpile to Gonn3. Create component modeln - Createsrc/std/lang/model/spec_xtalk/com_go.cljn - Define how xtalk data structures transpile to Gonn4. Create testsn - Createtest/std/lang/model/spec_xtalk/fn_go_test.cljn - Createtest/std/lang/model/spec_xtalk/com_go_test.cljnn5. Audit coveragen ```clojuren (manage/xtalk-language-status {:langs [:go]})n ;; Check model-count, test-count, spec coveragen ```nn6. Generate operator testsn ```clojuren (manage/scaffold-xtalk-grammar-tests {:write true})n ;; Generates grammar tests for Gon ```
4.3.2 Workflow 2: Improve Language Coverage
When you have missing features (:spec-missing > 0):
- Identify missing featuresn ```clojuren (manage/missing-by-language)n ;; Shows which operators are not yet implementedn ```nn2. Update language modeln - Edit
src/std/lang/model/spec_xtalk/fn_<lang>.cljn - Add implementation for missing operator (change from:abstractto:emit)nn3. Verify coveragen ```clojuren (manage/support-matrix [:your-lang])n ;; Check that missing count decreasedn ```nn4. Add testsn - Create appropriate test cases in language-specific test filen - Run:lein test :only hara.lang.model.spec-xtalk.<lang>-test
4.3.3 Workflow 3: Audit Test Coverage
Ensure every model definition has corresponding tests:
;; Get model and test inventory\n(let [model (manage/xtalk-model-inventory)\n tests (manage/xtalk-test-inventory)]\n (doseq [[lang model-entry] model]\n (let [test-entry (get tests lang)\n model-count (:model-count model-entry)\n test-count (:test-count test-entry)\n coverage (if (pos? model-count) \n (double (/ test-count model-count)) \n 0.0)]\n (println (format \"%s: %d models, %d tests (%.1f%%)\"\n lang model-count test-count (* 100 coverage))))))
4.4 Command Reference
4.4.1 CLI Commands
All commands are invoked via lein manage with the pattern:
lein manage <task> [selectors] [options]
Xtalk-specific tasks:
4.4.2 API Reference
From code.manage.xtalk namespace:
4.4.2.1 Inventory Functions
(xtalk-model-inventory) ; => {:js {...}, :lua {...}, ...}\n(xtalk-test-inventory) ; => {:js {...}, :lua {...}, ...}\n(xtalk-runtime-inventory) ; => {:js {...}, :lua {...}, ...}\n(xtalk-spec-inventory) ; => {:js {...}, :lua {...}, ...}\n(xtalk-language-status) ; => {:js {...}, :lua {...}, ...}
4.4.2.2 Audit Functions
(installed-languages) ; => [:js :lua :python :r]\n(audit-languages) ; => [:js :lua :python]\n(audit-languages [:js :go]) ; => [:js] (filtered to installed)\n(support-matrix) ; => {:languages [...] :features [...] :status {...}}\n(support-matrix [:js :lua]) ; => Support matrix for specific languages\n(support-matrix nil [:x:if]) ; => Support matrix for specific features\n(missing-by-language) ; => {:lua [...] :go [...] :r [...]}\n(missing-by-feature) ; => {:x:async [:lua] :x:spread [...] ...}
4.4.2.3 Metadata Functions
(xtalk-categories) ; => [:xtalk-conditional :xtalk-loop ...]\n(xtalk-op-map) ; => {:x:if {...} :x:do {...} ...}\n(xtalk-symbols) ; => [:x:if :x:do :x:try ...]
4.4.2.4 Generation Functions
(generate-xtalk-ops) ; Generate/update operator inventory\n(scaffold-xtalk-grammar-tests) ; Generate grammar test skeleton\n(separate-runtime-tests) ; Split tests by runtime language\n(visualize-support) ; Display formatted support matrix
4.5 File Structure
4.5.1 Source Organization
src/std/lang/\n├── manage/\n│ ├── xtalk_audit.clj # Audit and feature tracking\n│ ├── xtalk_ops.clj # Operation inventory management\n│ ├── xtalk_scaffold.clj # Test generation and scaffolding\n│ └── manage.clj # Main coordination\n├── model/\n│ └── spec_xtalk/\n│ ├── fn_js.clj # JavaScript function transpilation\n│ ├── fn_lua.clj # Lua function transpilation\n│ ├── fn_python.clj # Python function transpilation\n│ ├── com_js.clj # JavaScript component transpilation\n│ └── ...\n├── typed/\n│ ├── xtalk.clj # Core typed system\n│ ├── xtalk_analysis.clj # Type analysis\n│ ├── xtalk_check.clj # Type checking\n│ ├── xtalk_parse.clj # Parsing typed definitions\n│ └── xtalk_ops.clj # Typed operations\n└── base/\n └── grammar_xtalk.clj # Core xtalk grammar definitions
4.5.2 Configuration
config/xtalk/\n└── xtalk_ops.edn # Operation inventory (managed)
4.5.3 Tests
test/std/lang/\n└── model/\n └── spec_xtalk/\n ├── fn_js_test.clj # JavaScript function tests\n ├── fn_lua_test.clj # Lua function tests\n ├── com_js_test.clj # JavaScript component tests\n └── ...
4.6 Common Issues and Solutions
4.6.1 Issue 1: Missing Runtime for Language
Problem: (manage/xtalk-runtime-inventory) shows :runtime-installed? false for a language you need.
Solution:
- Install the runtime:
apt-get install nodejs(for JavaScript), etc.n- Or, if it's already installed, ensure it's on your PATH:which noden- Verify with(manage/installed-languages)
4.6.2 Issue 2: Features Showing as Missing
Problem: Language has :spec-missing > 0 when adding a new language.
Solution:
- Check which features are missing:n ```clojuren (manage/missing-by-language)n ```n2. For each missing feature, update the grammar in the language's model files:n - Edit
src/std/lang/model/spec_xtalk/fn_<lang>.cljn - Change operator status from:abstractto:emitwith implementationn3. Optionally provide a partial implementation with:abstract :emitto indicate n work-in-progress
4.6.3 Issue 3: Test Coverage is Low
Problem: A language has models but few tests (:coverage < 1.0).
Solution:
- Identify uncovered models:n ```clojuren (let [model (manage/xtalk-model-inventory)n tests (manage/xtalk-test-inventory)]n (doseq [[lang entry] model]n (when (> (:model-count entry) (get-in tests [lang :test-count] 0))n (println "Coverage gap for" lang))))n ```n2. Create corresponding test files in
test/std/lang/model/spec_xtalk/n3. Run:lein test :only hara.lang.model.spec_xtalk.<lang>-test
4.6.4 Issue 4: Support Matrix Shows Incomplete Data
Problem: Some languages or features aren't appearing in (manage/support-matrix).
Solution:
- Ensure the language has been required/loaded:
(manage/audit-languages)n- Check that grammar definitions are properly tagged withx:prefixn- Verify the language grammar is properly registered in nsrc/std/lang/base/registry.clj
4.6.5 Issue 5: Operator Inventory is Stale
Problem: New operators aren't appearing in (manage/xtalk-op-map).
Solution:
- Regenerate the inventory:n ```clojuren (manage/generate-xtalk-ops {:write true})n ```n2. This reads the latest grammar definitions and updates
config/xtalk/xtalk_ops.ednn3. Verify with:(keys (manage/xtalk-op-map))
4.7 Advanced Tasks
4.7.1 Analyzing Operator Metadata
;; Get details for a specific operator\n(get (manage/xtalk-op-map) :x:if)\n;; => {:op :x:if\n;; :category :xtalk-conditional\n;; :canonical-symbol ...\n;; :symbols [x:if]\n;; :class :infix\n;; :requires [...]\n;; :emit :code\n;; :macro ...\n;; :doc \"...\"\n;; :cases [...]}
4.7.2 Tracking Language Feature Gaps
;; For each language, see which features block full implementation\n(let [matrix (manage/support-matrix)]\n (doseq [[lang summary] (:summary matrix)]\n (let [missing (:missing summary)]\n (when (pos? missing)\n (println (format \"%s needs %d features\" lang missing))))))
4.7.3 Custom Coverage Analysis
;; Calculate detailed metrics\n(defn coverage-report []\n (let [langs (manage/audit-languages)\n model (manage/xtalk-model-inventory)\n tests (manage/xtalk-test-inventory)\n specs (manage/xtalk-spec-inventory)]\n (doseq [lang langs\n :let [m (get model lang) t (get tests lang) s (get specs lang)]]\n (when m\n (printf \"%-8s | Models: %3d | Tests: %3d | Cov: %5.1f%% | \"\n lang (:model-count m) (:test-count t)\n (* 100.0 (/ (:test-count t 0) (:model-count m 1))))\n (printf \"Features: %2d impl, %2d missing\\n\"\n (:spec-implemented s 0) (:spec-missing s 0))))))\n\n(coverage-report)
4.8 Related Guides
- code.manage - General code management and maintenance tasksn- code.test - Testing framework used for xtalk testsn- std.task - Task execution engine underlying management operationsn- README.md - Overview of
hara.langand xtalk system
5 Comprehensive Usage Guide for deftype.pg
Comprehensive Usage Guide for deftype.pgnnThis guide provides a detailed overview of deftype.pg, the macro used within the hara.lang ecosystem to define PostgreSQL table schemas. It covers basic syntax, column configuration, relationships, and advanced settings.nn## 1. Introductionnndeftype.pg serves as the primary mechanism for defining data models in the rt.postgres runtime. It declaratively defines tables, columns, constraints, and relationships, which are then compiled into standard PostgreSQL CREATE TABLE statements. It integrates with the project's registry for type checking and reference resolution.nn## 2. Basic SyntaxnnThe basic structure of a deftype.pg form is:nn```clojuren(deftype.pg TableNamen [column-1 {:key val ...}n column-2 {:key val ...}]n {table-options})n```nn- TableName: A symbol representing the table name.n- Column Vector: A vector of alternating column names (symbols/keywords) and property maps.n- Table Options: A map for table-level configuration (e.g., constraints, partitioning).nn## 3. Column DefinitionsnnEach column is defined by a property map.nn### Core Propertiesnn| Key | Description | Example |n| :--- | :--- | :--- |n| :type | The PostgreSQL type (e.g., :text, :int, :uuid, :boolean, :jsonb). | {:type :text} |n| :primary | Marks the column as a primary key. | {:primary true} |n| :required | Adds a NOT NULL constraint. | {:required true} |n| :unique | Adds a UNIQUE constraint. | {:unique true} |n| :default | Sets the default value. | {:default "now()"} |n| :enum | Specifies an enum type definition. | {:type :enum :enum {:ns 'my.ns/MyEnum}} |nn### Examplenn```clojuren(deftype.pg Usern [:id {:type :uuid :primary true}n :name {:type :text :required true}n :role {:type :enum :enum {:ns 'my.app/UserRole}}])n```nn## 4. SQL Customization (:sql)nnThe :sql sub-map allows fine-grained control over the generated SQL for a specific column.nn- :cascade: Adds ON DELETE CASCADE (often used with foreign keys).n- :check: Adds a column-level CHECK constraint.n- :unique: If a string is provided, groups columns into a composite unique constraint.n- :index: Creates an index for the column.n - true: Simple index.n - {:using :gin :where ...}: Advanced index configuration.nn```clojuren(deftype.pg Itemn [:data {:type :jsonb :sql {:index {:using :gin}}}n :age {:type :int :sql {:check (> age 0)}}])n```nn## 5. Relationships (Foreign Keys)nnForeign keys are defined using the :ref type. The system automatically handles naming (e.g., appending _id) and validation.nn### Syntaxnn```clojuren:owner {:type :refn :ref {:ns 'target.namespace/TargetTable}}n```nn### Featuresn- Automatic Naming: A column named :user referencing User becomes user_id in SQL.n- Hydration: Validates that the referenced namespace and table exist in the project registry.n- Cross-Module References: Supports referencing tables in different schemas/modules.nn## 6. Table OptionsnnThe third argument to deftype.pg handles table-wide settings.nn### ConstraintsnDefine named CHECK constraints.nn```clojuren{:constraints {:checkpositivebalance (> balance 0)}}n```nn### PartitioningnDefine table partitioning strategies.nn```clojuren{:partition-by [:range :createdat]}n```nn### Custom SQLnAppend raw SQL fragments to the table definition.nn```clojuren{:custom ["CONSTRAINT customrule ..."]}n```nn## 7. Metadata ConfigurationnnBehavior can be controlled via metadata on the table symbol.nn- Schema: ^{:static/schema "public"} defines the PostgreSQL schema.n- Tracking: ^{:track [...]} adds audit columns (e.g., created_at, updated_at) via a tracking strategy (e.g., rt.postgres.grammar.common-tracker/TrackingMin).n- Lifecycle: ^{:final true} prevents DROP TABLE IF EXISTS generation (useful for production).n- Composition: ^{:prepend [...] :append [...]} mixes in column definitions from fragments.nn## 8. Advanced Featuresnn### Composite KeysnDefining multiple columns with :primary true creates a composite primary key.nn### Composite UniquesnUse the :sql {:unique "group_name"} property on multiple columns to create a composite unique constraint.nn### IndexesnIndexes are automatically collected and generated as separate CREATE INDEX statements.nn## 9. Comprehensive Examplenn```clojuren(deftype.pg ^{:static/schema "app"n :track [rt.postgres.grammar.common-tracker/TrackingMin]}n Ordern [:id {:type :uuid :primary true}n :user {:type :ref :ref {:ns 'app/User} :sql {:cascade true}}n :status {:type :text :default "pending"}n :items {:type :jsonb :sql {:index {:using :gin}}}n :total {:type :numeric :required true}]n {:constraints {:positive_total (> total 0)}})n```n
6 Introduction to hara.lang
Here is the content recreated in Markdown format:nn—nn# Introduction to hara.langnn## What is hara.lang?nnstd.lang is a Domain-Specific Language (DSL) designed to simplify the process of defining database operations and structures programmatically. It bridges the gap between high-level programming concepts (e.g., functions and data structures) and database-specific logic like SQL/PLpgSQL.nnWith hara.lang, developers can:n- Write database functions, types, and procedures in a declarative, high-level syntax.n- Automatically generate PostgreSQL-compatible SQL scripts for execution.n- Leverage features like validations, inline helper calls, and error handling seamlessly.nn### Why Use hara.lang?nn- Consistency: Define database operations in a structured, reusable way.n- Ease of Use: Abstracts SQL intricacies while giving access to advanced features.n- Integration: Embeds naturally into larger projects using functional programming languages like Clojure.n- Maintainability: Ensures clean and organized database-related code.nn---nn## Key Features of hara.langnn### 1. Function Definitionsnhara.lang allows you to define database functions easily:nn```clojuren(defn.pg example-functionn "A simple example function"n {:added "1.0"}n ([:uuid iinput :text imessage]n (let [output (str "Processed: " imessage)]n (return output))))n```nnGenerates:nn```sqlnCREATE OR REPLACE FUNCTION examplefunction(n iinput UUID,n imessage TEXTn) RETURNS TEXT AS $$nDECLAREn output TEXT;nBEGINn output := 'Processed: ' || imessage;n RETURN output;nEND;n$$ LANGUAGE plpgsql;n```nn### 2. Type DefinitionsnCreate custom types and schemas programmatically:nn```clojuren(deftype.pg example-typen [:id {:type :uuid :primary true}n :name {:type :text :required true}n :createdat {:type :timestamp :default "now()"}])n```nnGenerates:nn```sqlnCREATE TABLE exampletype (n id UUID PRIMARY KEY,n name TEXT NOT NULL,n createdat TIMESTAMP DEFAULT now()n);n```nn### 3. Validations and AssertionsnInline checks for input validation:nn```clojuren(pg/assert [value :is-not-null] [:error/tag "Value cannot be null"])n```nn### 4. Dynamic SQL ConstructionnEmbed SQL logic dynamically:nn```clojuren(pg/t:select app/UserAccount {:where {:email iemail}})n```nnGenerates:nn```sqlnSELECT * FROM app.UserAccount WHERE email = iemail;n```nn---nn## Getting Started with Tutorialsnn### Tutorial 1: Setting Up Your EnvironmentnnGoal: Install and configure hara.lang in your project.nn1. Prerequisites:n - PostgreSQL installed locally or accessible via a database connection.n - Familiarity with SQL and basic programming concepts.nn2. Setup:n - Install hara.lang dependencies in your project.n - Connect to your PostgreSQL database.nn3. Example Setup Script:nn```clojuren(ns myproject.coren (:require [hara.lang :as l]n [rt.postgres :as pg]))nn;; Example database connectionn(pg/setup {:dbname "mydatabase"n :user "user"n :password "password"n :host "localhost"})n```nn---nn### Tutorial 2: Defining Your First FunctionnnGoal: Create a simple function to greet users.nn1. Write Your Function in hara.lang:nn```clojuren(defn.pg greet-usern "Greets a user by name"n {:added "1.0"}n ([:text iname]n (let [greeting (str "Hello, " iname "!")]n (return greeting))))n```nn2. Generated SQL:nn```sqlnCREATE OR REPLACE FUNCTION greetuser(n iname TEXTn) RETURNS TEXT AS $$nDECLAREn greeting TEXT;nBEGINn greeting := 'Hello, ' || iname || '!';n RETURN greeting;nEND;n$$ LANGUAGE plpgsql;n```nn3. Test Your Function:nn```sqlnSELECT greetuser('Alice');n-- Output: "Hello, Alice!"n```nn---nn### Tutorial 3: Using Validations and Error HandlingnnGoal: Extend the greet-user function with input validation.nn1. Add Validation Logic:nn```clojuren(defn.pg greet-usern "Greets a user by name"n {:added "1.1"}n ([:text iname]n (pg/assert [iname :is-not-null] [:error/invalid-input "Name cannot be null"])n (let [greeting (str "Hello, " iname "!")]n (return greeting))))n```nn2. Generated SQL:nn```sqlnCREATE OR REPLACE FUNCTION greetuser(n iname TEXTn) RETURNS TEXT AS $$nDECLAREn greeting TEXT;nBEGINn IF iname IS NULL THENn RAISE EXCEPTION 'Name cannot be null';n END IF;n greeting := 'Hello, ' || iname || '!';n RETURN greeting;nEND;n$$ LANGUAGE plpgsql;n```nn—nn### Tutorial 4: Creating Custom TypesnnGoal: Define a custom PostgreSQL table for users.nn1. Define Your Table:nn```clojuren(deftype.pg usern [:id {:type :uuid :primary true}n :name {:type :text :required true}n :email {:type :citext :unique true}n :createdat {:type :timestamp :default "now()"}])n```nn2. Generated SQL:nn```sqlnCREATE TABLE user (n id UUID PRIMARY KEY,n name TEXT NOT NULL,n email CITEXT UNIQUE,n createdat TIMESTAMP DEFAULT now()n);n```nn—nn### Tutorial 5: Advanced: Writing ProceduresnnGoal: Combine multiple operations into a single procedure.nn1. Create a Registration Procedure:nn```clojuren(defn.pg register-usern "Registers a new user"n {:added "1.0"}n ([:uuid iuserid :jsonb iuserdata]n (let [vname (iuserdata ->> "name")n vemail (iuserdata ->> "email")]n (pg/assert [vemail :is-not-null] [:error/invalid-input "Email cannot be null"])n (pg/t:insert user {:id iuserid :name vname :email vemail})n (return (str "User registered: " vname)))))n```nn2. Generated SQL:nn```sqlnCREATE OR REPLACE FUNCTION registeruser(n iuserid UUID,n iuserdata JSONBn) RETURNS TEXT AS $$nDECLAREn vname TEXT;n vemail TEXT;nBEGINn vname := iuserdata ->> 'name';n vemail := iuserdata ->> 'email';nn IF vemail IS NULL THENn RAISE EXCEPTION 'Email cannot be null';n END IF;nn INSERT INTO user (id, name, email)n VALUES (iuserid, vname, vemail);nn RETURN 'User registered: ' || v_name;nEND;n$$ LANGUAGE plpgsql;n```nn—nnLet me know if you'd like to refine or expand this Markdown-based guide! 😊