fancy 0.5.0 → 0.6.0
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.
- 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
|
}
|