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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0c45704ab8c82b9f4d22ff2b09e893637268825
4
- data.tar.gz: 6f92595032263d7d955814b7f781818edfabdd8b
3
+ metadata.gz: 2f79f3d05ec02a277eb9cc2b52e66cfb0bc167df
4
+ data.tar.gz: a1e2bd7b861f7bddd40b47092e508d542b78a89a
5
5
  SHA512:
6
- metadata.gz: 4a216b4f765b5755b3c8b7f01d7079e9d547219c70e0434155114e2c01dccd9d57e21273d99ea121765a9d6137b5ca31219ace852e12aa654edc6fcb1d863568
7
- data.tar.gz: 19d1a9786dae75dcb96180a4ac483b5470f3f4f3fcc3c4884139e2884d21af774330ff4fffe9c1c1582f212cd781b77f7cb2eceed895996d8ceec653f5d28baf
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
- _TODO_
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
 
@@ -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
@@ -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
@@ -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 "@#{self.to_s}".to_sym
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
@@ -1,3 +1,3 @@
1
1
  module RubyLisp
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -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
- (.count x))))
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 string?
144
- (fn string? [x]
145
- (.is_a? x Kernel::String)))
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 (+ "@" (.to_s kw))) value)))
269
+ (.instance_variable_set obj (.to_sym (+ "@" (name kw))) value)))
241
270
 
242
271
  (def class
243
272
  (fn class [x]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Yarwood