fancy 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +2 -0
- data/README.md +6 -1
- data/bin/fancy +6 -0
- data/bin/ifancy +44 -3
- data/boot/fancy_ext/module.rb +4 -0
- data/boot/fancy_ext/object.rb +4 -0
- data/boot/rbx-compiler/compiler/ast/block.rb +29 -1
- data/boot/rbx-compiler/compiler/ast/identifier.rb +6 -0
- data/boot/rbx-compiler/compiler/ast/message_send.rb +1 -0
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/lexer.lex +2 -0
- data/boot/rbx-compiler/parser/parser.rb +6 -0
- data/boot/rbx-compiler/parser/parser.y +14 -1
- data/doc/api/fancy.jsonp +1 -1
- data/doc/features.md +24 -0
- data/examples/99bottles.fy +5 -0
- data/examples/conditions_exceptions.fy +9 -0
- data/examples/conditions_parsing.fy +68 -0
- data/examples/greeter.fy +9 -0
- data/examples/html_generator.fy +59 -29
- data/examples/webserver/webserver.fy +8 -11
- data/lib/argv.fy +6 -0
- data/lib/array.fy +17 -35
- data/lib/block.fy +82 -1
- data/lib/boot.fy +4 -2
- data/lib/compiler.fy +2 -2
- data/lib/compiler/ast/block.fy +24 -20
- data/lib/compiler/ast/message_send.fy +11 -0
- data/lib/contracts.fy +60 -0
- data/lib/dynamic_slot_object.fy +61 -0
- data/lib/enumerable.fy +432 -394
- data/lib/enumerator.fy +152 -150
- data/lib/fdoc.fy +4 -17
- data/lib/fiber.fy +4 -10
- data/lib/file.fy +33 -25
- data/lib/future.fy +59 -5
- data/lib/hash.fy +54 -1
- data/lib/html.fy +107 -0
- data/lib/kvo.fy +173 -0
- data/lib/main.fy +6 -2
- data/lib/message_sink.fy +19 -0
- data/lib/number.fy +48 -0
- data/lib/object.fy +65 -13
- data/lib/package.fy +12 -2
- data/lib/package/dependency.fy +13 -0
- data/lib/package/dependency_installer.fy +27 -0
- data/lib/package/installer.fy +4 -10
- data/lib/package/uninstaller.fy +1 -3
- data/lib/parser/ext/lexer.lex +8 -3
- data/lib/parser/ext/parser.y +4 -1
- data/lib/parser/methods.fy +7 -3
- data/lib/range.fy +1 -1
- data/lib/rbx.fy +2 -1
- data/lib/rbx/array.fy +28 -12
- data/lib/rbx/bignum.fy +1 -1
- data/lib/rbx/block.fy +27 -0
- data/lib/rbx/console.fy +6 -6
- data/lib/rbx/date.fy +6 -1
- data/lib/rbx/documentation.fy +8 -3
- data/lib/rbx/exception.fy +5 -0
- data/lib/rbx/file.fy +40 -7
- data/lib/rbx/fixnum.fy +12 -1
- data/lib/rbx/method.fy +9 -2
- data/lib/rbx/module.fy +24 -0
- data/lib/rbx/regexp.fy +8 -0
- data/lib/rbx/string.fy +23 -7
- data/lib/rbx/tcp_server.fy +4 -2
- data/lib/rbx/tcp_socket.fy +14 -0
- data/lib/remote_object.fy +59 -0
- data/lib/set.fy +15 -4
- data/lib/string.fy +38 -5
- data/lib/stringio.fy +1 -0
- data/lib/symbol.fy +4 -0
- data/lib/system.fy +22 -0
- data/lib/thread_pool.fy +2 -2
- data/lib/tuple.fy +18 -1
- data/lib/vars.fy +17 -0
- data/lib/version.fy +1 -1
- data/ruby_lib/fancy +6 -0
- data/tests/array.fy +30 -0
- data/tests/block.fy +106 -0
- data/tests/class.fy +19 -0
- data/tests/enumerable.fy +1 -1
- data/tests/enumerator.fy +5 -5
- data/tests/file.fy +28 -0
- data/tests/fixnum.fy +0 -50
- data/tests/future.fy +9 -24
- data/tests/hash.fy +35 -0
- data/tests/html.fy +33 -0
- data/tests/kvo.fy +101 -0
- data/tests/number.fy +75 -0
- data/tests/object.fy +50 -3
- data/tests/string.fy +19 -10
- data/tests/symbol.fy +5 -0
- data/tests/tuple.fy +7 -0
- data/tools/fancy-mode.el +5 -1
- metadata +22 -21
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/Makefile +0 -156
- data/boot/rbx-compiler/parser/lexer.c +0 -2310
- data/boot/rbx-compiler/parser/lexer.h +0 -315
- data/boot/rbx-compiler/parser/parser.c +0 -2946
- data/boot/rbx-compiler/parser/parser.h +0 -151
- data/lib/fiber_pool.fy +0 -78
- data/lib/method.fy +0 -6
- data/lib/parser/ext/Makefile +0 -156
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +0 -2392
- data/lib/parser/ext/lexer.h +0 -315
- data/lib/parser/ext/parser.c +0 -3251
- data/lib/parser/ext/parser.h +0 -161
data/lib/rbx/tcp_server.fy
CHANGED
data/lib/rbx/tcp_socket.fy
CHANGED
@@ -5,6 +5,8 @@ class TCPSocket {
|
|
5
5
|
TCP Socket class.
|
6
6
|
"""
|
7
7
|
|
8
|
+
forwards_unary_ruby_methods
|
9
|
+
|
8
10
|
def TCPSocket open: server port: port {
|
9
11
|
"""
|
10
12
|
@server Server hostname to open Socket on.
|
@@ -15,4 +17,16 @@ class TCPSocket {
|
|
15
17
|
|
16
18
|
open(server, port)
|
17
19
|
}
|
20
|
+
|
21
|
+
def send: msg flags: flags (0) {
|
22
|
+
send(msg, flags)
|
23
|
+
}
|
24
|
+
|
25
|
+
def recv: maxlen {
|
26
|
+
recv(maxlen)
|
27
|
+
}
|
28
|
+
|
29
|
+
def read: n {
|
30
|
+
read(n)
|
31
|
+
}
|
18
32
|
}
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require: "fyzmq"
|
2
|
+
|
3
|
+
class RemoteObject : BasicObject {
|
4
|
+
def initialize {
|
5
|
+
@context = ZMQ Context new
|
6
|
+
@sock = @context socket: ZMQ PAIR
|
7
|
+
Thread new: { self receive_remote }
|
8
|
+
}
|
9
|
+
|
10
|
+
def bind: port {
|
11
|
+
bind_addr = "ipc://127.0.0.1:#{port}"
|
12
|
+
"Binding #{self} to #{bind_addr}" println
|
13
|
+
@sock bind: bind_addr
|
14
|
+
}
|
15
|
+
|
16
|
+
def connect_port: port {
|
17
|
+
connect: "ipc://127.0.0.1:#{port}"
|
18
|
+
}
|
19
|
+
|
20
|
+
def connect: addr {
|
21
|
+
@sock connect: addr
|
22
|
+
"Connected #{self} to #{addr}" println
|
23
|
+
}
|
24
|
+
|
25
|
+
def receive_remote {
|
26
|
+
loop: {
|
27
|
+
"waiting" println
|
28
|
+
msg = @sock recv
|
29
|
+
"Got: #{msg inspect}" println
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
def send_async: message with_params: p {
|
34
|
+
"sending" println
|
35
|
+
@sock send: "foo" # ('send, message, p inspect)
|
36
|
+
}
|
37
|
+
|
38
|
+
def to_s {
|
39
|
+
"#<RemoteObject:#{object_id to_s: 16}>"
|
40
|
+
}
|
41
|
+
|
42
|
+
def inspect {
|
43
|
+
to_s
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
r = RemoteObject new
|
48
|
+
|
49
|
+
if: (ARGV includes?: "bind") then: {
|
50
|
+
r bind: 3001
|
51
|
+
} else: {
|
52
|
+
r connect_port: 3001
|
53
|
+
}
|
54
|
+
|
55
|
+
Thread sleep: 2
|
56
|
+
|
57
|
+
r send_async: 'to_s: with_params: 16
|
58
|
+
|
59
|
+
Thread sleep: 2
|
data/lib/set.fy
CHANGED
@@ -3,11 +3,11 @@ class Set {
|
|
3
3
|
A simple Set data structure class.
|
4
4
|
"""
|
5
5
|
|
6
|
-
include:
|
6
|
+
include: Fancy Enumerable
|
7
7
|
|
8
8
|
def initialize: values {
|
9
9
|
"""
|
10
|
-
@values @
|
10
|
+
@values @Fancy::Enumerable@ of values to be used as values for @self.
|
11
11
|
|
12
12
|
Initialize a new Set with a given collection of values.
|
13
13
|
"""
|
@@ -70,7 +70,7 @@ class Set {
|
|
70
70
|
|
71
71
|
def Set [values] {
|
72
72
|
"""
|
73
|
-
@values @
|
73
|
+
@values @Fancy::Enumerable@ of values used for new Set.
|
74
74
|
|
75
75
|
Initialize a new Set with a given collection of values.
|
76
76
|
"""
|
@@ -95,12 +95,23 @@ class Set {
|
|
95
95
|
@value Value to be checked for if included in @self.
|
96
96
|
@return @true if @value in @self, @false otherwise.
|
97
97
|
|
98
|
-
Indicates, if the Set includes
|
98
|
+
Indicates, if the Set includes @value.
|
99
99
|
"""
|
100
100
|
|
101
101
|
@hash includes?: value
|
102
102
|
}
|
103
103
|
|
104
|
+
def [value] {
|
105
|
+
"""
|
106
|
+
@value Value to be checked for if included in @self.
|
107
|
+
@return @true if @value is in @self, @nil otherwise.
|
108
|
+
|
109
|
+
Indicates, if the Set includes @value.
|
110
|
+
"""
|
111
|
+
|
112
|
+
@hash[value]
|
113
|
+
}
|
114
|
+
|
104
115
|
def each: block {
|
105
116
|
"""
|
106
117
|
@block @Block@ to be called with each value in @self.
|
data/lib/string.fy
CHANGED
@@ -4,11 +4,29 @@ class String {
|
|
4
4
|
All literal Strings within Fancy code are instances of the String
|
5
5
|
class.
|
6
6
|
|
7
|
-
They also include
|
7
|
+
They also include @Fancy::Enumerable@, which means you can use all the
|
8
8
|
common sequence methods on them, like +map:+, +select:+ etc.
|
9
9
|
"""
|
10
10
|
|
11
|
-
include:
|
11
|
+
include: Fancy Enumerable
|
12
|
+
|
13
|
+
instance_method: '== . documentation: """
|
14
|
+
Compares @self to another @String@ and returns @true, if equal, @false otherwise.
|
15
|
+
"""
|
16
|
+
|
17
|
+
instance_method: 'uppercase . documentation: """
|
18
|
+
@return Uppercased version of @self.
|
19
|
+
|
20
|
+
Example:
|
21
|
+
\"hello world\" uppercase # => \"HELLO WORLD\"
|
22
|
+
"""
|
23
|
+
|
24
|
+
instance_method: 'lowercase . documentation: """
|
25
|
+
@return Lowercased version of @self.
|
26
|
+
|
27
|
+
Example:
|
28
|
+
\"HELLO WORLD\" lowercase # => \"hello world\"
|
29
|
+
"""
|
12
30
|
|
13
31
|
def ++ other {
|
14
32
|
"""
|
@@ -52,7 +70,9 @@ class String {
|
|
52
70
|
@return @String@ that is the num-fold concatenation of @self.
|
53
71
|
|
54
72
|
Returns a @String@ that is the num-fold concatenation of itself.
|
55
|
-
|
73
|
+
|
74
|
+
Example:
|
75
|
+
\"foo\" * 3 # => \"foofoofoo\"
|
56
76
|
"""
|
57
77
|
|
58
78
|
str = ""
|
@@ -66,6 +86,7 @@ class String {
|
|
66
86
|
"""
|
67
87
|
@return @Array@ of all the whitespace seperated words in @self.
|
68
88
|
|
89
|
+
Example:
|
69
90
|
\"hello world\" words # => [\"hello\", \"world\"]
|
70
91
|
"""
|
71
92
|
|
@@ -156,13 +177,25 @@ class String {
|
|
156
177
|
|
157
178
|
def bytes {
|
158
179
|
"""
|
159
|
-
@return @
|
180
|
+
@return @Fancy::Enumerator@ of all bytes (@Fixnum@ values) in @self.
|
160
181
|
"""
|
161
182
|
|
162
183
|
enum = bytes()
|
163
184
|
def enum each: block {
|
164
185
|
each(&block)
|
165
186
|
}
|
166
|
-
|
187
|
+
Fancy Enumerator new: enum
|
188
|
+
}
|
189
|
+
|
190
|
+
def relative_path: path {
|
191
|
+
"""
|
192
|
+
@path Relative path to @self.
|
193
|
+
@return Absolute @File@ path relative to @self.
|
194
|
+
|
195
|
+
Example:
|
196
|
+
__FILE__ relative: \"../foo/bar\"
|
197
|
+
"""
|
198
|
+
|
199
|
+
File expand_path: $ File dirname(self) + "/" + path
|
167
200
|
}
|
168
201
|
}
|
data/lib/stringio.fy
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require: "rbx/stringio"
|
data/lib/symbol.fy
CHANGED
data/lib/system.fy
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
class System {
|
2
|
+
def System abort {
|
3
|
+
"""
|
4
|
+
Exits the current running Fancy process (application) with an exit
|
5
|
+
code of 1 (indicating failure).
|
6
|
+
"""
|
7
|
+
|
8
|
+
exit: 1
|
9
|
+
}
|
10
|
+
|
11
|
+
def System abort: message {
|
12
|
+
"""
|
13
|
+
@message Error message to be printed before aborting programm execution.
|
14
|
+
|
15
|
+
Prints a given message on @*stderr* and then exits with an exit
|
16
|
+
code of 1 (indicating failure).
|
17
|
+
"""
|
18
|
+
|
19
|
+
*stderr* println: message
|
20
|
+
abort
|
21
|
+
}
|
22
|
+
}
|
data/lib/thread_pool.fy
CHANGED
@@ -76,12 +76,12 @@ class ThreadPool {
|
|
76
76
|
|
77
77
|
# Kills all threads
|
78
78
|
def close {
|
79
|
-
@executors each:
|
79
|
+
@executors each: @{ close }
|
80
80
|
}
|
81
81
|
|
82
82
|
# Sleeps and blocks until the task queue is finished executing
|
83
83
|
def join {
|
84
|
-
{ Thread sleep: 0.1 } until: { { @queue empty? } && { @executors all?:
|
84
|
+
{ Thread sleep: 0.1 } until: { { @queue empty? } && { @executors all?: @{ active not } } }
|
85
85
|
}
|
86
86
|
|
87
87
|
class Completable {
|
data/lib/tuple.fy
CHANGED
@@ -4,7 +4,24 @@ class Tuple {
|
|
4
4
|
elements.
|
5
5
|
"""
|
6
6
|
|
7
|
-
include:
|
7
|
+
include: Fancy Enumerable
|
8
|
+
|
9
|
+
def Tuple with_values: values {
|
10
|
+
"""
|
11
|
+
@values Values of the @Tuple@ to be created.
|
12
|
+
|
13
|
+
Creates a new @Tuple@ with the @values passed in.
|
14
|
+
|
15
|
+
Example:
|
16
|
+
Tuple with_values: [1,2,3] # => (1,2,3)
|
17
|
+
"""
|
18
|
+
|
19
|
+
t = Tuple new: $ values size
|
20
|
+
values each_with_index: |v i| {
|
21
|
+
t[i]: v
|
22
|
+
}
|
23
|
+
t
|
24
|
+
}
|
8
25
|
|
9
26
|
def [idx] {
|
10
27
|
"""
|
data/lib/vars.fy
CHANGED
@@ -1,3 +1,20 @@
|
|
1
1
|
*stdin* = STDIN
|
2
2
|
*stdout* = STDOUT
|
3
3
|
*stderr* = STDERR
|
4
|
+
|
5
|
+
__AFTER__BOOTSTRAP__: {
|
6
|
+
*stdin* documentation: """
|
7
|
+
The Standard Input stream.
|
8
|
+
Can be rebound to any @IO@ stream via @Object#let:be:in:@.
|
9
|
+
"""
|
10
|
+
|
11
|
+
*stdout* documentation: """
|
12
|
+
The Standard Output stream.
|
13
|
+
Can be rebound to any @IO@ stream via @Object#let:be:in:@.
|
14
|
+
"""
|
15
|
+
|
16
|
+
*stderr* documentation: """
|
17
|
+
The Standard Error Output stream.
|
18
|
+
Can be rebound to any @IO@ stream via @Object#let:be:in:@.
|
19
|
+
"""
|
20
|
+
}
|
data/lib/version.fy
CHANGED
data/ruby_lib/fancy
CHANGED
@@ -4,6 +4,12 @@
|
|
4
4
|
base = File.dirname(__FILE__)
|
5
5
|
require File.expand_path("../boot/fancy_ext", base)
|
6
6
|
|
7
|
+
class Object
|
8
|
+
define_method("__AFTER__BOOTSTRAP__:") do |block|
|
9
|
+
block.call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
# Use the bootstrapping code loader.
|
8
14
|
require File.expand_path("../boot/load", base)
|
9
15
|
|
data/tests/array.fy
CHANGED
@@ -61,6 +61,26 @@ FancySpec describe: Array with: {
|
|
61
61
|
arr size is: 0
|
62
62
|
}
|
63
63
|
|
64
|
+
it: "creates a new array with a given default value" with: 'new: when: {
|
65
|
+
arr = Array new: 5
|
66
|
+
arr size is: 5
|
67
|
+
arr each: |x| {
|
68
|
+
x is: nil
|
69
|
+
}
|
70
|
+
|
71
|
+
arr = Array new: 5 with: "hello"
|
72
|
+
arr size is: 5
|
73
|
+
arr each: |x| {
|
74
|
+
x is: "hello"
|
75
|
+
}
|
76
|
+
|
77
|
+
arr = Array new: 5 with: { 2 + 3 }
|
78
|
+
arr size is: 5
|
79
|
+
arr each: |x| {
|
80
|
+
x is: 5
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
64
84
|
it: "returns the correct value via index access" with: 'at: when: {
|
65
85
|
arr = ['a, 10, "hello, world"]
|
66
86
|
arr at: 2 . is: "hello, world"
|
@@ -522,4 +542,14 @@ FancySpec describe: Array with: {
|
|
522
542
|
|
523
543
|
(20,30,40) in_groups_of: 2 . is: [[20,30], [40]]
|
524
544
|
}
|
545
|
+
|
546
|
+
it: "returns a hash" with: 'to_hash when: {
|
547
|
+
[] to_hash is: <[]>
|
548
|
+
[[1,2],[3,4]] to_hash is: <[1 => 2, 3 => 4]>
|
549
|
+
}
|
550
|
+
|
551
|
+
it: "returns a hash based on a key-block" with: 'to_hash: when: {
|
552
|
+
[] to_hash: @{ size } . is: <[]>
|
553
|
+
[[1,2],[3,4,5]] to_hash: @{ size } . is: <[2 => [1,2], 3 => [3,4,5]]>
|
554
|
+
}
|
525
555
|
}
|
data/tests/block.fy
CHANGED
@@ -113,6 +113,28 @@ FancySpec describe: Block with: {
|
|
113
113
|
[1,2,3] map: @{to_s * 3} . is: ["111", "222", "333"]
|
114
114
|
}
|
115
115
|
|
116
|
+
it: "calls the block as a partial block, converting it to implicit message sends to the first argument" when: {
|
117
|
+
b = @{
|
118
|
+
inspect println
|
119
|
+
class println
|
120
|
+
* 2 println
|
121
|
+
'test println
|
122
|
+
}
|
123
|
+
|
124
|
+
require: "stringio"
|
125
|
+
|
126
|
+
out = StringIO new
|
127
|
+
let: '*stdout* be: out in: {
|
128
|
+
b call: ["Hello, World"]
|
129
|
+
b call: [1]
|
130
|
+
b call: [1, 2, 3]
|
131
|
+
}
|
132
|
+
expected_output = ["\"Hello, World\"\nString\nHello, WorldHello, World\ntest\n",
|
133
|
+
"1\nFixnum\n2\ntest\n",
|
134
|
+
"[1, 2, 3]\nArray\n1\n2\n3\n1\n2\n3\ntest\n"] join
|
135
|
+
out string is: expected_output
|
136
|
+
}
|
137
|
+
|
116
138
|
it: "executes a match clause if the block returns a true-ish value" with: '=== when: {
|
117
139
|
def do_match: val {
|
118
140
|
match val {
|
@@ -196,4 +218,88 @@ FancySpec describe: Block with: {
|
|
196
218
|
b2("hello") is: ("hello" * 5)
|
197
219
|
b2("foo") is: (b2 call: ["foo"])
|
198
220
|
}
|
221
|
+
|
222
|
+
it: "dynamically creates a object with slots defined in a Block" with: 'to_object when: {
|
223
|
+
o = {
|
224
|
+
name: "John Connor"
|
225
|
+
age: 12
|
226
|
+
city: "Los Angeles"
|
227
|
+
persecuted_by: $ {
|
228
|
+
name: "The Terminator"
|
229
|
+
age: 'unknown
|
230
|
+
} to_object
|
231
|
+
} to_object
|
232
|
+
|
233
|
+
o name is: "John Connor"
|
234
|
+
o age is: 12
|
235
|
+
o city is: "Los Angeles"
|
236
|
+
o persecuted_by do: {
|
237
|
+
name is: "The Terminator"
|
238
|
+
age is: 'unknown
|
239
|
+
}
|
240
|
+
}
|
241
|
+
|
242
|
+
it: "dynamically creates a hash with keys and values defined in a Block" with: 'to_hash when: {
|
243
|
+
{ } to_hash is: <[]>
|
244
|
+
{ foo: "bar" } to_hash is: <['foo => "bar"]>
|
245
|
+
{ foo: "bar"; bar: "baz" } to_hash is: <['foo => "bar", 'bar => "baz"]>
|
246
|
+
h = {
|
247
|
+
name: "John Connor"
|
248
|
+
age: 12
|
249
|
+
city: "Los Angeles"
|
250
|
+
persecuted_by: $ {
|
251
|
+
name: "The Terminator"
|
252
|
+
age: 'unknown
|
253
|
+
} to_hash
|
254
|
+
} to_hash
|
255
|
+
|
256
|
+
h is: <['name => "John Connor",
|
257
|
+
'age => 12,
|
258
|
+
'city => "Los Angeles",
|
259
|
+
'persecuted_by => <[
|
260
|
+
'name => "The Terminator",
|
261
|
+
'age => 'unknown
|
262
|
+
]>
|
263
|
+
]>
|
264
|
+
}
|
265
|
+
|
266
|
+
it: "dynamically creates a hash with keys and values defined in a Block (deep)" with: 'to_hash_deep when: {
|
267
|
+
{ } to_hash_deep is: <[]>
|
268
|
+
{ foo: "bar" } to_hash_deep is: <['foo => "bar"]>
|
269
|
+
h = {
|
270
|
+
name: "John Connor"
|
271
|
+
age: 12
|
272
|
+
city: "Los Angeles"
|
273
|
+
persecuted_by: {
|
274
|
+
name: "The Terminator"
|
275
|
+
age: 'unknown
|
276
|
+
}
|
277
|
+
} to_hash_deep
|
278
|
+
|
279
|
+
h is: <['name => "John Connor",
|
280
|
+
'age => 12,
|
281
|
+
'city => "Los Angeles",
|
282
|
+
'persecuted_by => <[
|
283
|
+
'name => "The Terminator",
|
284
|
+
'age => 'unknown
|
285
|
+
]>
|
286
|
+
]>
|
287
|
+
h['persecuted_by] is: <['name => "The Terminator", 'age => 'unknown]>
|
288
|
+
}
|
289
|
+
|
290
|
+
it: "dynamically creates an array with values defined in a Block" with: 'to_a when: {
|
291
|
+
{ } to_a is: []
|
292
|
+
{ foo } to_a is: ['foo]
|
293
|
+
{ foo; bar; baz } to_a is: ['foo, 'bar, 'baz]
|
294
|
+
{ foo bar baz } to_a is: ['foo, 'bar, 'baz]
|
295
|
+
{
|
296
|
+
name: "Chris"
|
297
|
+
age: 24
|
298
|
+
city: "San Francisco"
|
299
|
+
male; programmer; happy
|
300
|
+
} to_a is: [['name, "Chris"],
|
301
|
+
['age, 24],
|
302
|
+
['city, "San Francisco"],
|
303
|
+
'male, 'programmer, 'happy]
|
304
|
+
}
|
199
305
|
}
|