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 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