fancy 0.3.2 → 0.3.3
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/README.md +4 -1
- data/Rakefile +8 -0
- data/bin/fyi +25 -20
- data/bin/ifancy +39 -5
- data/{extconf.rb → boot/extconf.rb} +1 -1
- data/boot/fancy_ext/block_env.rb +0 -14
- data/boot/fancy_ext/kernel.rb +6 -2
- data/boot/rbx-compiler/parser/fancy_parser.bundle +0 -0
- data/examples/actor.fy +37 -0
- data/examples/armstrong_numbers.fy +1 -1
- data/examples/curl_async.fy +37 -0
- data/examples/echo.fy +1 -1
- data/examples/factorial.fy +1 -1
- data/examples/future_composition.fy +20 -0
- data/examples/game_of_life.fy +2 -2
- data/examples/person.fy +4 -8
- data/examples/rbx/blocks.fy +1 -1
- data/examples/return.fy +1 -1
- data/examples/struct.fy +9 -0
- data/lib/argv.fy +2 -2
- data/lib/array.fy +157 -0
- data/lib/block.fy +18 -1
- data/lib/boot.fy +5 -1
- data/lib/compiler/ast/class_def.fy +1 -1
- data/lib/compiler/ast/identifier.fy +2 -2
- data/lib/compiler/ast/message_send.fy +2 -2
- data/lib/compiler/ast/method_def.fy +2 -2
- data/lib/compiler/ast/try_catch.fy +5 -1
- data/lib/documentation.fy +1 -1
- data/lib/enumerable.fy +3 -7
- data/lib/enumerator.fy +77 -0
- data/lib/false_class.fy +52 -0
- data/lib/fancy_spec.fy +40 -12
- data/lib/fdoc.fy +2 -2
- data/lib/file.fy +8 -1
- data/lib/future.fy +23 -2
- data/lib/iteration.fy +60 -0
- data/lib/main.fy +4 -4
- data/lib/nil_class.fy +14 -22
- data/lib/number.fy +51 -0
- data/lib/object.fy +126 -43
- data/lib/package/installer.fy +1 -1
- data/lib/parser/ext/lexer.lex +6 -1
- data/lib/parser/ext/parser.y +18 -0
- data/lib/parser/methods.fy +20 -2
- data/lib/proxy.fy +20 -3
- data/lib/rbx.fy +0 -1
- data/lib/rbx/array.fy +4 -138
- data/lib/rbx/block.fy +25 -1
- data/lib/rbx/class.fy +21 -0
- data/lib/rbx/exception.fy +1 -0
- data/lib/rbx/fiber.fy +1 -0
- data/lib/rbx/file.fy +8 -0
- data/lib/rbx/integer.fy +0 -8
- data/lib/rbx/method.fy +34 -7
- data/lib/rbx/no_method_error.fy +8 -1
- data/lib/rbx/object.fy +3 -32
- data/lib/rbx/range.fy +13 -1
- data/lib/rbx/regexp.fy +3 -0
- data/lib/rbx/string.fy +6 -1
- data/lib/rbx/system.fy +20 -2
- data/lib/set.fy +2 -2
- data/lib/string.fy +1 -1
- data/lib/struct.fy +15 -12
- data/lib/symbol.fy +2 -2
- data/lib/true_class.fy +16 -20
- data/lib/version.fy +1 -1
- data/tests/argv.fy +1 -0
- data/tests/array.fy +33 -2
- data/tests/block.fy +44 -0
- data/tests/class.fy +102 -88
- data/tests/control_flow.fy +131 -8
- data/tests/enumerator.fy +85 -0
- data/tests/exception.fy +13 -13
- data/tests/file.fy +4 -13
- data/tests/future.fy +26 -0
- data/tests/method.fy +83 -72
- data/tests/nil_class.fy +20 -13
- data/tests/number.fy +16 -9
- data/tests/object.fy +39 -20
- data/tests/string.fy +7 -0
- data/tests/true_class.fy +4 -4
- data/tools/fancy-mode.el +1 -1
- metadata +15 -20
- data/boot/compiler/parser/ext/fancy_parser.bundle +0 -0
- data/boot/rbx-compiler/parser/Makefile +0 -162
- data/boot/rbx-compiler/parser/lexer.c +0 -2316
- data/boot/rbx-compiler/parser/lexer.h +0 -315
- data/boot/rbx-compiler/parser/parser.c +0 -3105
- data/boot/rbx-compiler/parser/parser.h +0 -114
- data/lib/lazy_array.fy +0 -23
- data/lib/parser/ext/Makefile +0 -162
- data/lib/parser/ext/fancy_parser.bundle +0 -0
- data/lib/parser/ext/lexer.c +0 -2360
- data/lib/parser/ext/lexer.h +0 -315
- data/lib/parser/ext/parser.c +0 -3382
- data/lib/parser/ext/parser.h +0 -118
- data/lib/rbx/false_class.fy +0 -58
data/README.md
CHANGED
@@ -133,9 +133,12 @@ Ruby method invocation supports passing a block variable to Ruby as a proc.
|
|
133
133
|
- Calling, using and extending arbitrary Ruby classes and methods
|
134
134
|
(including C-extensions), as well as passing blocks and splat
|
135
135
|
arguments to Ruby methods.
|
136
|
+
- Futures (`future = object @ message`)
|
137
|
+
- Async message sends (`object @@ message`)
|
138
|
+
|
136
139
|
|
137
140
|
##What's still missing?
|
138
|
-
-
|
141
|
+
- Some concurrency stuff (e.g. language syntax for actors)
|
139
142
|
- Some more advanced stuff, e.g. runtime inspection of method calls
|
140
143
|
via MethodContext etc. (saved for later)
|
141
144
|
|
data/Rakefile
CHANGED
@@ -255,6 +255,14 @@ task :test do
|
|
255
255
|
*Dir.glob(_("tests/*.fy"))
|
256
256
|
end
|
257
257
|
|
258
|
+
task :tests do
|
259
|
+
task(:test).invoke
|
260
|
+
end
|
261
|
+
|
262
|
+
task "tests/" do
|
263
|
+
task(:test).invoke
|
264
|
+
end
|
265
|
+
|
258
266
|
task :bootstrap => ["compiler:bootstrap"]
|
259
267
|
|
260
268
|
task :default => [:bootstrap_if_needed, :compile]
|
data/bin/fyi
CHANGED
@@ -1,25 +1,30 @@
|
|
1
1
|
#!/usr/bin/env fancy
|
2
2
|
# -*- fancy -*-
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
4
|
+
try {
|
5
|
+
if: (ARGV[1]) then: |ident| {
|
6
|
+
documentation = nil
|
7
|
+
if: (ident includes?: "#") then: {
|
8
|
+
parts = ident split: "#"
|
9
|
+
obj = parts[0] eval
|
10
|
+
if: (parts[1]) then: |method_name| {
|
11
|
+
method = obj instance_method: $ parts[1]
|
12
|
+
documentation = method documentation
|
13
|
+
}
|
13
14
|
}
|
15
|
+
# just print documentation for class here
|
16
|
+
obj = ident eval
|
17
|
+
documentation = obj documentation
|
18
|
+
"Documentation for: '#{ident}':" println
|
19
|
+
documentation println
|
20
|
+
} else: {
|
21
|
+
["Prints the documentation string for a given object or one if its methods",
|
22
|
+
"Usage:",
|
23
|
+
"fyi [ObjectIdentifier]",
|
24
|
+
"fyi [ObjectIdentifier]#[MethodName]",
|
25
|
+
"",
|
26
|
+
"Example: fyi Array#each:"] println
|
14
27
|
}
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
} else: {
|
19
|
-
["Prints the documentation string for a given object or one if its methods",
|
20
|
-
"Usage:",
|
21
|
-
"fyi [ObjectIdentifier]",
|
22
|
-
"fyi [ObjectIdentifier]#[MethodName]",
|
23
|
-
"",
|
24
|
-
"Example: fyi Array#each:"] println
|
25
|
-
}
|
28
|
+
} catch Exception => e {
|
29
|
+
"ERROR: #{e message}" println
|
30
|
+
}
|
data/bin/ifancy
CHANGED
@@ -6,6 +6,9 @@ require("readline")
|
|
6
6
|
["Welcome to the (still very simple) Fancy REPL",
|
7
7
|
"Fancy " ++ FANCY_VERSION] println
|
8
8
|
|
9
|
+
HISTORY_FILE = File expand_path("~/.fancy_history")
|
10
|
+
HISTORY = []
|
11
|
+
|
9
12
|
ARGV rest each: |file| {
|
10
13
|
"LOADING: " ++ file println
|
11
14
|
require: file
|
@@ -14,26 +17,55 @@ ARGV rest each: |file| {
|
|
14
17
|
# handle SIGINT
|
15
18
|
trap("INT") {
|
16
19
|
"Quitting." println
|
20
|
+
save_history
|
17
21
|
System exit
|
18
22
|
}
|
19
23
|
|
20
24
|
Console newline;
|
21
25
|
|
22
26
|
def double_or_empty?: line {
|
23
|
-
(line =~ /^\s*$/) or: (
|
27
|
+
(line =~ /^\s*$/) or: (HISTORY [-2] == line)
|
28
|
+
}
|
29
|
+
|
30
|
+
def load_history {
|
31
|
+
if: (File exists?: HISTORY_FILE) then: {
|
32
|
+
File open: HISTORY_FILE modes: ['read] with: |f| {
|
33
|
+
f readlines each: |l| {
|
34
|
+
l = l strip()
|
35
|
+
Readline HISTORY <<(l)
|
36
|
+
HISTORY << l
|
37
|
+
}
|
38
|
+
}
|
39
|
+
} else: {
|
40
|
+
File touch: HISTORY_FILE
|
41
|
+
}
|
24
42
|
}
|
25
43
|
|
44
|
+
def save_history {
|
45
|
+
puts("saving history")
|
46
|
+
unless: @history_saved do: {
|
47
|
+
File open: HISTORY_FILE modes: ['write] with: |f| {
|
48
|
+
HISTORY each: |l| {
|
49
|
+
f writeln: l
|
50
|
+
}
|
51
|
+
}
|
52
|
+
@history_saved = true
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
load_history
|
26
57
|
|
27
58
|
try {
|
28
59
|
bnd = binding()
|
29
60
|
|
30
|
-
{ Readline readline(">> ", true) }
|
31
|
-
|
32
|
-
double_or_empty?: line
|
61
|
+
while: { Readline readline(">> ", true) } do: |line| {
|
62
|
+
HISTORY << line
|
63
|
+
if: (double_or_empty?: line) then: {
|
33
64
|
Readline::HISTORY pop()
|
65
|
+
HISTORY pop()
|
34
66
|
}
|
35
67
|
|
36
|
-
line =~ /^\s*$/
|
68
|
+
unless: (line =~ /^\s*$/) do: {
|
37
69
|
try {
|
38
70
|
Fancy eval: line binding: bnd . inspect println
|
39
71
|
} catch Exception => e {
|
@@ -41,6 +73,8 @@ try {
|
|
41
73
|
}
|
42
74
|
}
|
43
75
|
}
|
76
|
+
save_history
|
44
77
|
} catch Interrupt => e {
|
78
|
+
save_history
|
45
79
|
System exit
|
46
80
|
}
|
data/boot/fancy_ext/block_env.rb
CHANGED
@@ -2,12 +2,6 @@
|
|
2
2
|
Block = Rubinius::BlockEnvironment
|
3
3
|
|
4
4
|
class Block
|
5
|
-
define_method("while_true:") do |block|
|
6
|
-
while tmp = self.call
|
7
|
-
block.call(tmp)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
5
|
# call without arguments
|
12
6
|
alias_method :":call", :call
|
13
7
|
|
@@ -22,12 +16,4 @@ class Block
|
|
22
16
|
call *args
|
23
17
|
end
|
24
18
|
end
|
25
|
-
|
26
|
-
define_method("call_with_receiver:") do |obj|
|
27
|
-
call_under obj, method.scope
|
28
|
-
end
|
29
|
-
|
30
|
-
define_method("call:with_receiver:") do |args, obj|
|
31
|
-
call_under obj, method.scope, *args
|
32
|
-
end
|
33
19
|
end
|
data/boot/fancy_ext/kernel.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Kernel
|
2
|
-
|
3
|
-
|
2
|
+
begin
|
3
|
+
alias_method ":metaclass", :metaclass
|
4
|
+
rescue
|
5
|
+
alias_method :":metaclass", :singleton_class
|
6
|
+
alias_method :metaclass, :singleton_class
|
7
|
+
end
|
4
8
|
|
5
9
|
def fancy_require(file, compile = false)
|
6
10
|
if compile
|
Binary file
|
data/examples/actor.fy
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require("actor")
|
2
|
+
class Actor {
|
3
|
+
alias_method: '! for_ruby: '<<
|
4
|
+
}
|
5
|
+
|
6
|
+
# Execute with Rubinius: rbx ex1.rb
|
7
|
+
|
8
|
+
def error_loop: block{
|
9
|
+
try {
|
10
|
+
loop: block
|
11
|
+
} catch Exception => ex {
|
12
|
+
ex message println
|
13
|
+
ex backtrace join: "\n"
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
pong = nil
|
18
|
+
ping = Actor spawn() {
|
19
|
+
error_loop: {
|
20
|
+
count = Actor receive()
|
21
|
+
"." print
|
22
|
+
{ return count println } if: (count > 1000)
|
23
|
+
pong ! (count + 1)
|
24
|
+
}
|
25
|
+
}
|
26
|
+
pong = Actor.spawn() {
|
27
|
+
error_loop: {
|
28
|
+
count = Actor receive()
|
29
|
+
"-" print
|
30
|
+
{ return count println } if: (count > 1000)
|
31
|
+
ping ! (count + 1)
|
32
|
+
}
|
33
|
+
}
|
34
|
+
ping ! 1
|
35
|
+
|
36
|
+
# Let the actors process while the main thread sleeps...
|
37
|
+
Thread sleep: 1
|
@@ -0,0 +1,37 @@
|
|
1
|
+
def async curl: url {
|
2
|
+
out = System pipe: "curl #{url}"
|
3
|
+
return out read # return string of html
|
4
|
+
}
|
5
|
+
|
6
|
+
def async curl_urls: urls {
|
7
|
+
results = []
|
8
|
+
urls each: |url| {
|
9
|
+
# await means it will suspend the current context until the curl: has finished
|
10
|
+
# and will resume with the line below
|
11
|
+
data = await curl: url
|
12
|
+
results << data
|
13
|
+
}
|
14
|
+
return results
|
15
|
+
}
|
16
|
+
|
17
|
+
URLS = ["http://www.backtype.com", "http://www.fancy-lang.org", "http://tech.backtype.com"]
|
18
|
+
|
19
|
+
# usage (runs it asynchronously and returns a future that will hold the data when its done)
|
20
|
+
f = curl_urls: URLS
|
21
|
+
|
22
|
+
# do something else...
|
23
|
+
# then after some time access the data:
|
24
|
+
|
25
|
+
f value each: |html| {
|
26
|
+
html println
|
27
|
+
}
|
28
|
+
|
29
|
+
# or hook it up with something to do when its done:
|
30
|
+
curl_urls: URLS && |data| {
|
31
|
+
data each: |html| {
|
32
|
+
html println
|
33
|
+
}
|
34
|
+
}
|
35
|
+
|
36
|
+
# shorter version of above:
|
37
|
+
curl_urls: URLS && @{each: 'println}
|
data/examples/echo.fy
CHANGED
data/examples/factorial.fy
CHANGED
@@ -0,0 +1,20 @@
|
|
1
|
+
# example of composing futures:
|
2
|
+
|
3
|
+
def do_large_computation: x {
|
4
|
+
x upto: (x ** x)
|
5
|
+
}
|
6
|
+
|
7
|
+
# Future#&& takes a Block (or a Callable - something that implements 'call:)
|
8
|
+
# and creates a new Future that executes the given Block with the value of the first Future
|
9
|
+
# when it has finished its computation. This makes pipelining tasks easy.
|
10
|
+
|
11
|
+
f = self @ do_large_computation: 5 && @{select: 'even?} && @{inspect println}
|
12
|
+
"computing .. " println
|
13
|
+
f value
|
14
|
+
|
15
|
+
#the above is the same as:
|
16
|
+
# f = self @ do_large_computation: 5
|
17
|
+
# f = f when_done: @{select: 'even?}
|
18
|
+
# f = f when_done: @{inspect println}
|
19
|
+
# "computing .. " println
|
20
|
+
# f value
|
data/examples/game_of_life.fy
CHANGED
@@ -72,7 +72,7 @@ class World {
|
|
72
72
|
def was_alive?: pos {
|
73
73
|
"Indicates, if a cell ([row,column]) was alive in the last generation."
|
74
74
|
|
75
|
-
@last_alive[pos[0]]
|
75
|
+
@last_alive[pos[0]] if_true: |row| {
|
76
76
|
row[pos[1]] == 1
|
77
77
|
}
|
78
78
|
}
|
@@ -115,7 +115,7 @@ class World {
|
|
115
115
|
column = pos[1]
|
116
116
|
|
117
117
|
neighbors = @offsets map: |o| {
|
118
|
-
@matrix[row + (o[0])]
|
118
|
+
@matrix[row + (o[0])] if_true: |r| {
|
119
119
|
r[column + (o[1])]
|
120
120
|
}
|
121
121
|
}
|
data/examples/person.fy
CHANGED
@@ -2,9 +2,8 @@
|
|
2
2
|
# Annotated example of fancy's classes mechanism
|
3
3
|
|
4
4
|
class City {
|
5
|
-
read_slots: ['
|
6
|
-
def initialize: name {
|
7
|
-
@name = name
|
5
|
+
read_slots: ['name]
|
6
|
+
def initialize: @name {
|
8
7
|
}
|
9
8
|
|
10
9
|
def to_s {
|
@@ -24,10 +23,7 @@ class Person {
|
|
24
23
|
# method but having initialize: replaced by new:.
|
25
24
|
# So in this case: Person##new:age:city:
|
26
25
|
# which calls this instance method internally
|
27
|
-
def initialize: name age: age city: city {
|
28
|
-
@name = name
|
29
|
-
@age = age
|
30
|
-
@city = city
|
26
|
+
def initialize: @name age: @age city: @city {
|
31
27
|
}
|
32
28
|
|
33
29
|
def go_to: city {
|
@@ -50,7 +46,7 @@ class Person {
|
|
50
46
|
}
|
51
47
|
|
52
48
|
def to_s {
|
53
|
-
"Person:
|
49
|
+
"Person: #{@name}, #{@age} years old, living in #{@city}"
|
54
50
|
}
|
55
51
|
}
|
56
52
|
|
data/examples/rbx/blocks.fy
CHANGED
data/examples/return.fy
CHANGED
data/examples/struct.fy
ADDED
data/lib/argv.fy
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
def ARGV for_option: op_name do: block {
|
2
2
|
"Runs a given block if an option is in ARGV."
|
3
3
|
|
4
|
-
ARGV index: op_name .
|
4
|
+
ARGV index: op_name . if_true: |idx| {
|
5
5
|
if: (block argcount > 0) then: {
|
6
|
-
ARGV[idx + 1]
|
6
|
+
ARGV[idx + 1] if_true: |arg| {
|
7
7
|
block call: [arg]
|
8
8
|
ARGV remove_at: idx
|
9
9
|
ARGV remove_at: idx
|
data/lib/array.fy
CHANGED
@@ -7,6 +7,30 @@ class Array {
|
|
7
7
|
|
8
8
|
include: FancyEnumerable
|
9
9
|
|
10
|
+
def Array new: size {
|
11
|
+
"Creates a new Array with a given size (default value is nil)."
|
12
|
+
|
13
|
+
Array new: size with: nil
|
14
|
+
}
|
15
|
+
|
16
|
+
def clone {
|
17
|
+
"Clones (shallow copy) the Array."
|
18
|
+
new = []
|
19
|
+
each: |x| {
|
20
|
+
new << x
|
21
|
+
}
|
22
|
+
new
|
23
|
+
}
|
24
|
+
|
25
|
+
def append: arr {
|
26
|
+
"Appends another Array onto this one."
|
27
|
+
|
28
|
+
arr each: |x| {
|
29
|
+
self << x
|
30
|
+
}
|
31
|
+
self
|
32
|
+
}
|
33
|
+
|
10
34
|
def [] index {
|
11
35
|
"""
|
12
36
|
Given an Array of 2 Numbers, it returns the sub-array between the
|
@@ -47,6 +71,42 @@ class Array {
|
|
47
71
|
from: 1 to: -1
|
48
72
|
}
|
49
73
|
|
74
|
+
def each: block {
|
75
|
+
"""
|
76
|
+
@block @Block@ to be called for each element in @self.
|
77
|
+
@return Return value of calling @block on the last item in @self.
|
78
|
+
|
79
|
+
Calls a given @Block@ with each element in the @Array@.
|
80
|
+
"""
|
81
|
+
|
82
|
+
try {
|
83
|
+
size times: |i| {
|
84
|
+
try {
|
85
|
+
block call: [at: i]
|
86
|
+
} catch (Fancy NextIteration) => ex {
|
87
|
+
}
|
88
|
+
}
|
89
|
+
self
|
90
|
+
} catch (Fancy BreakIteration) => ex {
|
91
|
+
ex return_value
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
def each_with_index: block {
|
96
|
+
"""
|
97
|
+
@block @Block@ to be called with each element and its inde in the @Array@.
|
98
|
+
|
99
|
+
Iterate over all elements in Array. Calls a given Block with each element and its index.
|
100
|
+
"""
|
101
|
+
|
102
|
+
i = 0
|
103
|
+
each: |x| {
|
104
|
+
block call: [x, i]
|
105
|
+
i = i + 1
|
106
|
+
}
|
107
|
+
nil
|
108
|
+
}
|
109
|
+
|
50
110
|
def =? other {
|
51
111
|
"""
|
52
112
|
@other Other @Array@ to compare this one to.
|
@@ -93,6 +153,7 @@ class Array {
|
|
93
153
|
return x
|
94
154
|
}
|
95
155
|
}
|
156
|
+
nil
|
96
157
|
}
|
97
158
|
|
98
159
|
def values_at: idx_arr {
|
@@ -219,9 +280,105 @@ class Array {
|
|
219
280
|
0 upto: (size - 1)
|
220
281
|
}
|
221
282
|
|
283
|
+
def indices_of: item {
|
284
|
+
"""
|
285
|
+
@item Item/Value for which a list of indices is requested within an @Array@.
|
286
|
+
@return @Array@ of all indices for a given value within an @Array@ (possibly empty).
|
287
|
+
|
288
|
+
Returns an Array of all indices of this item. Empty Array if item does not occur.
|
289
|
+
"""
|
290
|
+
|
291
|
+
tmp = []
|
292
|
+
each_with_index: |obj, idx| {
|
293
|
+
if: (item == obj) then: {
|
294
|
+
tmp << idx
|
295
|
+
}
|
296
|
+
}
|
297
|
+
tmp
|
298
|
+
}
|
299
|
+
|
300
|
+
def from: from to: to {
|
301
|
+
"""
|
302
|
+
@from Start index for sub-array.
|
303
|
+
@to End index ofr sub-array.
|
304
|
+
|
305
|
+
Returns sub-array starting at from: and going to to:
|
306
|
+
"""
|
307
|
+
|
308
|
+
if: (from < 0) then: {
|
309
|
+
from = size + from
|
310
|
+
}
|
311
|
+
if: (to < 0) then: {
|
312
|
+
to = size + to
|
313
|
+
}
|
314
|
+
subarr = []
|
315
|
+
from upto: to do: |i| {
|
316
|
+
subarr << (at: i)
|
317
|
+
}
|
318
|
+
subarr
|
319
|
+
}
|
320
|
+
|
321
|
+
def select: block {
|
322
|
+
"""
|
323
|
+
@block Predicate @Block@ to be used as filter.
|
324
|
+
@return @Array@ of all the elements for which @block doesn't yield @false or @nil.
|
325
|
+
|
326
|
+
Returns a new Array with all the elements in self that yield a
|
327
|
+
true-ish value when called with the given Block.
|
328
|
+
"""
|
329
|
+
|
330
|
+
tmp = []
|
331
|
+
each: |x| {
|
332
|
+
if: (block call: [x]) then: {
|
333
|
+
tmp << x
|
334
|
+
}
|
335
|
+
}
|
336
|
+
return tmp
|
337
|
+
}
|
338
|
+
|
339
|
+
def select_with_index: block {
|
340
|
+
"""
|
341
|
+
Same as select:, just gets also called with an additional argument
|
342
|
+
for each element's index value.
|
343
|
+
"""
|
344
|
+
|
345
|
+
tmp = []
|
346
|
+
each_with_index: |obj idx| {
|
347
|
+
if: (block call: [obj, idx]) then: {
|
348
|
+
tmp << [obj, idx]
|
349
|
+
}
|
350
|
+
}
|
351
|
+
tmp
|
352
|
+
}
|
353
|
+
|
222
354
|
def Array === object {
|
355
|
+
"""
|
356
|
+
@object Object to match @self against.
|
357
|
+
@return @nil, if no match, matched values (in an @Array) otherwise.
|
358
|
+
|
359
|
+
Matches an @Array against another object.
|
360
|
+
"""
|
361
|
+
|
223
362
|
if: (object is_a?: Array) then: {
|
224
363
|
return [object] + object
|
225
364
|
}
|
226
365
|
}
|
366
|
+
|
367
|
+
def sum {
|
368
|
+
"""
|
369
|
+
Calculates the sum of all the elements in the Enumerable
|
370
|
+
(assuming them to be Numbers (implementing '+' & '*')).
|
371
|
+
"""
|
372
|
+
|
373
|
+
reduce: |x y| { x + y } init_val: 0
|
374
|
+
}
|
375
|
+
|
376
|
+
def product {
|
377
|
+
"""
|
378
|
+
Calculates the product of all the elements in the Enumerable
|
379
|
+
(assuming them to be Numbers (implementing '+' & '*')).
|
380
|
+
"""
|
381
|
+
|
382
|
+
reduce: |x y| { x * y } init_val: 1
|
383
|
+
}
|
227
384
|
}
|