rbl 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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]
|