Skip to content

Commit 82dc68f

Browse files
authored
Update README with more info on glj vs embedding glojure (#84)
Signed-off-by: James Hamlin <jfhamlin@gmail.com>
1 parent 01d8a0a commit 82dc68f

File tree

1 file changed

+124
-8
lines changed

1 file changed

+124
-8
lines changed

README.md

Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,36 @@ user=>
5151

5252
## Usage
5353

54-
Here's a small example program that starts an HTTP server with a
55-
simple handler function that responds with the request body:
54+
Glojure can be used in two ways: as a standalone command-line tool (`glj`) or embedded within Go applications.
55+
56+
### Using the `glj` Command
57+
58+
The `glj` command provides a traditional Clojure development experience:
59+
60+
**Start a REPL (interactive session):**
61+
```
62+
$ glj
63+
user=> (+ 1 2 3)
64+
6
65+
user=> (println "Hello from Glojure!")
66+
Hello from Glojure!
67+
nil
68+
```
69+
70+
**Run a Clojure script:**
5671
```clojure
57-
;; example.glj
72+
;; hello.glj
73+
(println "Hello," (first *command-line-args*))
74+
```
75+
76+
```
77+
$ glj hello.glj World
78+
Hello, World
79+
```
80+
81+
**Create executable programs:**
82+
```clojure
83+
;; server.glj
5884
(ns example.server)
5985

6086
(defn echo-handler
@@ -63,20 +89,110 @@ simple handler function that responds with the request body:
6389
nil)
6490

6591
(net$http.Handle "/" (net$http.HandlerFunc echo-handler))
66-
92+
(println "Server starting on :8080...")
6793
(net$http.ListenAndServe ":8080" nil)
6894
```
6995

70-
Run it with the `glj` command:
7196
```
72-
$ glj ./example.glj
97+
$ glj server.glj
98+
Server starting on :8080...
7399
```
74100

101+
### Embedding Glojure in Go Applications
102+
103+
You can also embed Glojure as a scripting language within your Go applications. This is useful when you want to:
104+
- Add scriptable configuration to your Go application
105+
- Allow users to extend your application with Clojure plugins
106+
- Mix Go's performance with Clojure's expressiveness
107+
- Control the execution environment (custom I/O, sandboxing)
108+
109+
**Basic embedding example:**
110+
```go
111+
package main
112+
113+
import (
114+
"fmt"
115+
_ "github.com/glojurelang/glojure/pkg/glj" // Initialize Glojure
116+
"github.com/glojurelang/glojure/pkg/runtime"
117+
)
118+
119+
func main() {
120+
// Evaluate Clojure code
121+
result := runtime.ReadEval(`
122+
(defn factorial [n]
123+
(if (<= n 1)
124+
1
125+
(* n (factorial (dec n)))))
126+
(factorial 5)
127+
`)
128+
fmt.Printf("5! = %v\n", result) // 5! = 120
129+
}
130+
```
131+
132+
**Calling Go from Clojure and vice versa:**
133+
```go
134+
package main
135+
136+
import (
137+
"fmt"
138+
"github.com/glojurelang/glojure/pkg/glj"
139+
"github.com/glojurelang/glojure/pkg/runtime"
140+
)
141+
142+
// Define a Go function
143+
func greet(name string) string {
144+
return fmt.Sprintf("Hello, %s from Go!", name)
145+
}
146+
147+
func main() {
148+
// Make the Go function available to Clojure
149+
runtime.ReadEval(`(def greet-from-go nil)`) // placeholder
150+
greetVar := glj.Var("user", "greet-from-go")
151+
greetVar.SetRoot(greet)
152+
153+
// Use it from Clojure
154+
result := runtime.ReadEval(`(greet-from-go "Clojure")`)
155+
fmt.Println(result) // "Hello, Clojure from Go!"
156+
157+
// Call a Clojure function from Go
158+
runtime.ReadEval(`(defn add [x y] (+ x y))`)
159+
addFn := glj.Var("user", "add")
160+
sum := addFn.Invoke(10, 32)
161+
fmt.Printf("Sum: %v\n", sum) // Sum: 42
162+
}
75163
```
76-
$ curl localhost:8080 -d "sicp"
77-
sicp
164+
165+
**Accessing your own Go packages:**
166+
167+
When embedding Glojure, you can also expose your own Go packages or additional standard library packages using the package map approach described in the [Accessing additional Go packages](#accessing-additional-go-packages) section below. This allows embedded Clojure code to access any Go packages you choose to expose:
168+
169+
```go
170+
import (
171+
_ "github.com/glojurelang/glojure/pkg/glj"
172+
_ "your.app/gljimports" // Your generated package map
173+
)
174+
175+
// Now Clojure code can access your exposed packages
176+
runtime.ReadEval(`
177+
(your$package.YourFunction "arg")
178+
(another$package.Method)
179+
`)
78180
```
79181

182+
### When to Use Each Approach
183+
184+
**Use `glj` command for:**
185+
- Writing standalone Clojure programs
186+
- Interactive development with the REPL
187+
- Running Clojure scripts
188+
- Learning Clojure with Go interop
189+
190+
**Embed Glojure for:**
191+
- Adding scripting to an existing Go application
192+
- Building a platform that users extend with Clojure
193+
- Custom control over the Glojure execution environment
194+
- Mixing Go and Clojure in a single binary
195+
80196
### Interop
81197

82198
Glojure ships with interop with many standard library packages

0 commit comments

Comments
 (0)