rbl 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +171 -1
- data/lib/rubylisp/evaluator.rb +1 -1
- data/lib/rubylisp/printer.rb +2 -3
- data/lib/rubylisp/types.rb +23 -1
- data/lib/rubylisp/version.rb +1 -1
- data/rubylisp/core.rbl +35 -6
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f79f3d05ec02a277eb9cc2b52e66cfb0bc167df
|
4
|
+
data.tar.gz: a1e2bd7b861f7bddd40b47092e508d542b78a89a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5517a472833aad9bd8670c0aceb5b7fac368bf5cc0c96a12d1eed9352d563bd6599fcdceb006e4d6565567dfc1bd1a761ed395758b5448b3285b28e7b82aa51
|
7
|
+
data.tar.gz: ca25909f9d314a751ce37b51c5b82ca61e9cb26706bc68d60dddf7af896d8fb0c09ff3c2cbf07301397eae7cd1239024929c526b5a30225ff4b3a5b31b9ae6b3
|
data/README.md
CHANGED
@@ -36,7 +36,177 @@ I think I was right. Check it out, everyone -- you can write your Ruby scripts i
|
|
36
36
|
|
37
37
|
## Examples
|
38
38
|
|
39
|
-
|
39
|
+
### It's basically Clojure
|
40
|
+
|
41
|
+
Many of the affordances of the Clojure standard library are implemented as part
|
42
|
+
of the `rbl.core` namespace, which is included by default:
|
43
|
+
|
44
|
+
```clojure
|
45
|
+
user> (prn 'oh :hello "hi" 1 2.3 '(abc def) ['g ()] '{:h ijk})
|
46
|
+
oh :hello "hi" 1 2.3 (abc def) [g ()] {:h ijk}
|
47
|
+
nil
|
48
|
+
|
49
|
+
user> (take 20 (map inc (reverse (range 100))))
|
50
|
+
(101 100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82)
|
51
|
+
```
|
52
|
+
|
53
|
+
### Module/Class members
|
54
|
+
|
55
|
+
Members of Ruby modules and classes may be accessed in a familiar way, by appending `::` to the module or class:
|
56
|
+
|
57
|
+
```clojure
|
58
|
+
user> Kernel::ARGV
|
59
|
+
[]
|
60
|
+
|
61
|
+
user> Encoding::Converter::CR_NEWLINE_DECORATOR
|
62
|
+
8192
|
63
|
+
|
64
|
+
user> File::SEPARATOR
|
65
|
+
"/"
|
66
|
+
```
|
67
|
+
|
68
|
+
### Instance methods
|
69
|
+
|
70
|
+
Instance methods are called like Lisp functions. The reader will recognize any symbol that starts with `.` as an instance method, and send it as a message to the second element in the S-expression.
|
71
|
+
|
72
|
+
For example, `(.+ 1 2)` in RubyLisp is equivalent to `1.send(:+, 2)` in Ruby.
|
73
|
+
|
74
|
+
```clojure
|
75
|
+
user> (def f (File::open "/tmp/ugh.txt"))
|
76
|
+
#<File:/tmp/ugh.txt>
|
77
|
+
|
78
|
+
user> (.methods f)
|
79
|
+
[:size :path :truncate :lstat :atime :mtime :ctime :birthtime :chmod :chown ...
|
80
|
+
:! :== :!= :__send__ :equal? :instance_eval :instance_exec :__id__]
|
81
|
+
|
82
|
+
user> (.readbyte f)
|
83
|
+
66
|
84
|
+
|
85
|
+
user> (.size f)
|
86
|
+
365
|
87
|
+
```
|
88
|
+
|
89
|
+
### Immutable lists
|
90
|
+
|
91
|
+
The `list` function and `quote` form (e.g. `'(1 2 3)`) create immutable lists from the [Hamster][hamster] library:
|
92
|
+
|
93
|
+
```clojure
|
94
|
+
user> (class (list 1 2 3))
|
95
|
+
Hamster::Cons
|
96
|
+
|
97
|
+
user> (class '(abc def))
|
98
|
+
Hamster::Cons
|
99
|
+
|
100
|
+
user> (cons 'foo (quote (bar baz)))
|
101
|
+
(foo bar baz)
|
102
|
+
```
|
103
|
+
|
104
|
+
### Immutable vectors
|
105
|
+
|
106
|
+
Similarly, the `vector` and `vec` functions, as well as the square bracket literal form, create immutable vectors:
|
107
|
+
|
108
|
+
```clojure
|
109
|
+
user> (vector 1 2 3)
|
110
|
+
[1 2 3]
|
111
|
+
|
112
|
+
user> (vec (list 1 2 3))
|
113
|
+
[1 2 3]
|
114
|
+
|
115
|
+
user> (= [1 2 3] (vector 1 2 3))
|
116
|
+
true
|
117
|
+
|
118
|
+
user> (class [1 2 3])
|
119
|
+
Hamster::Vector
|
120
|
+
```
|
121
|
+
|
122
|
+
### Immutable maps
|
123
|
+
|
124
|
+
The `hash-map` function or the curly brace literal form can be used to create an immutable map:
|
125
|
+
|
126
|
+
```clojure
|
127
|
+
user> (map? (hash-map 'a 1 'b 2 'c 3))
|
128
|
+
true
|
129
|
+
|
130
|
+
user> {:a 1 "b" 2 'C 3}
|
131
|
+
{:a 1, C 3, "b" 2}
|
132
|
+
```
|
133
|
+
|
134
|
+
### Keywords (a.k.a. Symbols)
|
135
|
+
|
136
|
+
A keyword (in Clojure and therefore RubyLisp parlance) begins with a `:`. In Ruby, this data type is called, somewhat confusingly, a Symbol.
|
137
|
+
|
138
|
+
```clojure
|
139
|
+
user> (class :floop)
|
140
|
+
Symbol
|
141
|
+
|
142
|
+
user> (= :snoob (.to_sym "snoob"))
|
143
|
+
true
|
144
|
+
```
|
145
|
+
|
146
|
+
RubyLisp monkey-patches the Symbol class to make it behave like a Clojure keyword; you can call it like a function in order to retrieve a value from a hash map:
|
147
|
+
|
148
|
+
```clojure
|
149
|
+
user> (def barbara {:age 7 :species "greyhound"})
|
150
|
+
{:age 7, :species "greyhound"}
|
151
|
+
|
152
|
+
user> (:species barbara)
|
153
|
+
"greyhound"
|
154
|
+
```
|
155
|
+
|
156
|
+
### Instance variables
|
157
|
+
|
158
|
+
But that's not all -- you can also use keywords to get the value of an instance variable:
|
159
|
+
|
160
|
+
```clojure
|
161
|
+
; FIXME: This is a contrived example because it is not yet possible to easily
|
162
|
+
define a class in RubyLisp.
|
163
|
+
|
164
|
+
; rbl.core/=@ is provided as a convenient way to set instance variables on any
|
165
|
+
object... even a string!
|
166
|
+
user> (def s "my string")
|
167
|
+
"my string"
|
168
|
+
|
169
|
+
user> (=@ s :object_level 9001)
|
170
|
+
9001
|
171
|
+
|
172
|
+
; instance variables can then be retrieved by using a keyword as a function
|
173
|
+
user> (:object_level s)
|
174
|
+
9001
|
175
|
+
```
|
176
|
+
|
177
|
+
The above example is a little nonsensical (although a testament to the whimsy
|
178
|
+
of Ruby), but the pair of `=@` and keyword-used-as-a-function will be more
|
179
|
+
useful once there is a convenient way to define classes in RubyLisp.
|
180
|
+
|
181
|
+
### Mutable arrays and hashes
|
182
|
+
|
183
|
+
You can still use Ruby's mutable data structures via inter-op, if you insist:
|
184
|
+
|
185
|
+
```clojure
|
186
|
+
user> (def a (.dup (.to_a [1 2 3 4 5])))
|
187
|
+
[1 2 3 4 5]
|
188
|
+
|
189
|
+
user> (class a)
|
190
|
+
Array
|
191
|
+
|
192
|
+
user> (.<< a 6)
|
193
|
+
[1 2 3 4 5 6]
|
194
|
+
|
195
|
+
user> a
|
196
|
+
[1 2 3 4 5 6]
|
197
|
+
|
198
|
+
user> (def h (.to_h {}))
|
199
|
+
{}
|
200
|
+
|
201
|
+
user> (class h)
|
202
|
+
Hash
|
203
|
+
|
204
|
+
user> (.merge! h {:a 3})
|
205
|
+
{:a 3}
|
206
|
+
|
207
|
+
user> h
|
208
|
+
{:a 3}
|
209
|
+
```
|
40
210
|
|
41
211
|
## Installation
|
42
212
|
|
data/lib/rubylisp/evaluator.rb
CHANGED
@@ -196,7 +196,7 @@ module RubyLisp
|
|
196
196
|
fn, *args = input.value
|
197
197
|
quoted_form = args[0]
|
198
198
|
|
199
|
-
if [RubyLisp::List, RubyLisp::Vector].member? quoted_form.class
|
199
|
+
if [RubyLisp::HashMap, RubyLisp::List, RubyLisp::Vector].member? quoted_form.class
|
200
200
|
quoted_form.quote.value
|
201
201
|
else
|
202
202
|
quoted_form.quote
|
data/lib/rubylisp/printer.rb
CHANGED
@@ -18,11 +18,10 @@ module RubyLisp
|
|
18
18
|
pr_str x.to_hash
|
19
19
|
when Hamster::List
|
20
20
|
"(#{x.map {|item| pr_str(item)}.join(' ')})"
|
21
|
-
when RubyLisp::Keyword
|
22
|
-
":#{x.value}"
|
23
21
|
when RubyLisp::List
|
24
22
|
"(#{x.value.map {|item| pr_str(item)}.join(' ')})"
|
25
|
-
when RubyLisp::Symbol, RubyLisp::Int, RubyLisp::Float
|
23
|
+
when RubyLisp::Symbol, RubyLisp::String, RubyLisp::Int, RubyLisp::Float,
|
24
|
+
RubyLisp::Boolean, RubyLisp::Keyword
|
26
25
|
x.value
|
27
26
|
else
|
28
27
|
x.inspect
|
data/lib/rubylisp/types.rb
CHANGED
@@ -5,6 +5,10 @@ require 'hamster/vector'
|
|
5
5
|
|
6
6
|
# Monkey-patch Ruby symbols to act more like Clojure keywords
|
7
7
|
class Symbol
|
8
|
+
def name
|
9
|
+
to_s[1..-1]
|
10
|
+
end
|
11
|
+
|
8
12
|
def to_s
|
9
13
|
inspect
|
10
14
|
end
|
@@ -13,7 +17,7 @@ class Symbol
|
|
13
17
|
if [Hash, Hamster::Hash].member? target.class
|
14
18
|
target[self]
|
15
19
|
else
|
16
|
-
target.instance_variable_get "@#{
|
20
|
+
target.instance_variable_get "@#{name}".to_sym
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
@@ -33,6 +37,12 @@ module Hamster
|
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
40
|
+
class Hash
|
41
|
+
def to_s
|
42
|
+
"{#{to_hash.map {|k, v| "#{k} #{v}"}.join ", "}}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
36
46
|
class Vector
|
37
47
|
def to_s
|
38
48
|
"[#{join " "}]"
|
@@ -81,6 +91,18 @@ module RubyLisp
|
|
81
91
|
@value = Hamster::Hash[seq.each_slice(2).to_a]
|
82
92
|
end
|
83
93
|
end
|
94
|
+
|
95
|
+
def quote
|
96
|
+
@value.each {|k, v| k.quote; v.quote}
|
97
|
+
@quoted = true
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def unquote
|
102
|
+
@value.each {|k, v| k.unquote; v.unquote}
|
103
|
+
@quoted = false
|
104
|
+
self
|
105
|
+
end
|
84
106
|
end
|
85
107
|
|
86
108
|
class List < Value
|
data/lib/rubylisp/version.rb
CHANGED
data/rubylisp/core.rbl
CHANGED
@@ -118,11 +118,18 @@
|
|
118
118
|
(fn nil? [x]
|
119
119
|
(= nil x)))
|
120
120
|
|
121
|
+
(def string?
|
122
|
+
(fn string? [x]
|
123
|
+
(.is_a? x Kernel::String)))
|
124
|
+
|
125
|
+
;; TODO: implement & use cond
|
121
126
|
(def count
|
122
127
|
(fn count [x]
|
123
128
|
(if (nil? x)
|
124
129
|
0
|
125
|
-
(
|
130
|
+
(if (string? x)
|
131
|
+
(.count (seq x))
|
132
|
+
(.count x)))))
|
126
133
|
|
127
134
|
(def empty?
|
128
135
|
(fn empty? [coll]
|
@@ -140,9 +147,25 @@
|
|
140
147
|
(fn list? [x]
|
141
148
|
(.is_a? x Hamster::List)))
|
142
149
|
|
143
|
-
(def
|
144
|
-
(fn
|
145
|
-
(
|
150
|
+
(def vector
|
151
|
+
(fn vector [& args]
|
152
|
+
(Hamster::Vector::new args)))
|
153
|
+
|
154
|
+
(def vector?
|
155
|
+
(fn vector? [x]
|
156
|
+
(.is_a? x Hamster::Vector)))
|
157
|
+
|
158
|
+
(def vec
|
159
|
+
(fn vec [coll]
|
160
|
+
(Hamster::Vector::new coll)))
|
161
|
+
|
162
|
+
(def hash-map
|
163
|
+
(fn hash-map [& args]
|
164
|
+
(Hamster::Hash::new (.to_h (.each_slice args 2)))))
|
165
|
+
|
166
|
+
(def map?
|
167
|
+
(fn map? [x]
|
168
|
+
(.is_a? x Hamster::Hash)))
|
146
169
|
|
147
170
|
(def seq
|
148
171
|
(fn seq [x]
|
@@ -204,12 +227,18 @@
|
|
204
227
|
(apply Hamster::repeat args)
|
205
228
|
(apply Hamster::replicate args))))
|
206
229
|
|
207
|
-
;; STRINGS
|
230
|
+
;; STRINGS & KEYWORDS
|
208
231
|
|
209
232
|
(def str
|
210
233
|
(fn str [& args]
|
211
234
|
(.join (map .to_s args))))
|
212
235
|
|
236
|
+
(def name
|
237
|
+
(fn name [x]
|
238
|
+
(if (string? x)
|
239
|
+
x
|
240
|
+
(.name x))))
|
241
|
+
|
213
242
|
;; I/O
|
214
243
|
|
215
244
|
(def pr-str
|
@@ -237,7 +266,7 @@
|
|
237
266
|
|
238
267
|
(def =@
|
239
268
|
(fn =@ [obj kw value]
|
240
|
-
(.instance_variable_set obj (.to_sym (+ "@" (
|
269
|
+
(.instance_variable_set obj (.to_sym (+ "@" (name kw))) value)))
|
241
270
|
|
242
271
|
(def class
|
243
272
|
(fn class [x]
|