Gobyお試しメモ

# [Goby](https://github.com/goby-lang/goby)

## [Goby](https://github.com/goby-lang/goby)をセットアップ

[Via Homebrew (binary installation for Mac OS)](https://github.com/goby-lang/goby#a-via-homebrew-binary-installation-for-mac-os) でインストールするバージョンは、masterブランチと差分があるの[From Source](https://github.com/goby-lang/goby#b-from-source)でインストールします。

### Goをインストール

```sh
brew install go
echo 'export GOPATH=$HOME/go' >> $HOME/.zshrc
echo 'export PATH=$PATH:$GOPATH/bin' >> $HOME/.zshrc
source ~/.zshrc
go version
```

### [Goby](https://github.com/goby-lang/goby)をソースからインストール

```sh
go get github.com/goby-lang/goby
echo 'export GOBY_ROOT=$GOPATH/src/github.com/goby-lang/goby' >> $HOME/.zshrc
source ~/.zshrc
cd $GOPATH/src/github.com/goby-lang/goby
make install
goby
```

## REPL

### [Goby](https://github.com/goby-lang/goby)のREPLを起動する

```sh
goby -i
```

### [Goby](https://github.com/goby-lang/goby)のコードを実行する

```ruby
% goby -i
Goby 0.1.3 🤠 💀 😴
» [].methods
#» ["*", "+", "[]", "[]=", "any?", "at", "clear", "concat", "count", "delete_at", "dig", "each", "each_index", "empty?", "first", "flatten", "include?", "join", "last", "length", "map", "new", "pop", "push", "reduce", "reverse", "reverse_each", "rotate", "select", "shift", "unshift", "values_at", "!", "!=", "==", "block_given?", "class", "instance_variable_get", "instance_variable_set", "is_a?", "methods", "nil?", "object_id", "puts", "require", "require_relative", "send", "singleton_class", "sleep", "thread", "to_s"]
```

:+1:  https://github.com/goby-lang/goby/pull/421

```ruby
» a = [1, 2, 3, 4, 5]
#» [1, 2, 3, 4, 5]
» a.select do |e|
¤   e + 1 > 3
» end
#» [3, 4, 5]
```

```ruby
» [].methods.include?('select')
#» true
» [].methods.include?('reject')
#» false
```

## Array#rejectを追加する

### array.goをエディタで開く

```sh
cd $GOPATH/src/github.com/goby-lang/goby
subl -n vm/array.go
```

### array.goにArray#rejectを追加する

```diff
diff --git a/vm/array.go b/vm/array.go
index afd118a..d89201a 100644
--- a/vm/array.go
+++ b/vm/array.go
@@ -944,6 +944,44 @@ func builtinArrayInstanceMethods() []*BuiltinMethodObject {
 				}
 			},
 		},
+		{
+			// Loop through each element with the given block.
+			// Return a new array with each element that returns false from yield.
+			//
+			// ```ruby
+			// a = [1, 2, 3, 4, 5]
+			//
+			// a.reject do |e|
+			//   e + 1 > 3
+			// end
+			// # => [1, 2]
+			// ```
+			Name: "reject",
+			Fn: func(receiver Object, sourceLine int) builtinMethodBody {
+				return func(t *thread, args []Object, blockFrame *normalCallFrame) Object {
+					arr := receiver.(*ArrayObject)
+					var elements []Object
+
+					if blockFrame == nil {
+						return t.vm.initErrorObject(errors.InternalError, sourceLine, errors.CantYieldWithoutBlockFormat)
+					}
+
+					// If it's an empty array, pop the block's call frame
+					if len(arr.Elements) == 0 {
+						t.callFrameStack.pop()
+					}
+
+					for _, obj := range arr.Elements {
+						result := t.builtinMethodYield(blockFrame, obj)
+						if !result.Target.(*BooleanObject).value {
+							elements = append(elements, obj)
+						}
+					}
+
+					return t.vm.initArrayObject(elements)
+				}
+			},
+		},
 		{
 			// Removes the first element in the array and returns it.
 			//
```

### 修正をコンパイルする

```sh
% rm `which goby`
% make install
go install .
```

### Array#rejectを実行する

```ruby
% goby -i
Goby 0.1.3 😶 😄 😈
» [].methods
#» ["*", "+", "[]", "[]=", "any?", "at", "clear", "concat", "count", "delete_at", "dig", "each", "each_index", "empty?", "first", "flatten", "include?", "join", "last", "length", "map", "new", "pop", "push", "reduce", "reject", "reverse", "reverse_each", "rotate", "select", "shift", "unshift", "values_at", "!", "!=", "==", "block_given?", "class", "instance_variable_get", "instance_variable_set", "is_a?", "methods", "nil?", "object_id", "puts", "require", "require_relative", "send", "singleton_class", "sleep", "thread", "to_s"]
» [].methods.include?('reject')
#» true
» a = [1, 2, 3, 4, 5]
#» [1, 2, 3, 4, 5]
» a.reject do |e|
¤   e + 1 > 3
» end
#» [1, 2]
```

## Array#exclude?を追加する

### array.goからArray#include?を探す

```sh
% cat vm/array.go | grep include?
zsh: no matches found: include?
```

### array.gbをエディタで開く

```sh
cd $GOPATH/src/github.com/goby-lang/goby
subl -n lib/array.gb
```

```ruby
class Array
  def include?(x)
    any? do |i|
      i == x
    end
  end
end
```

### array.gbにArray#exclude?を追加する

```ruby
class Array
  def include?(x)
    any? do |i|
      i == x
    end
  end
  def exclude?(x)
    !include?(x)
  end
end
```

### 修正をコンパイルする

```sh
% rm `which goby`
% make install
go install .
```

### Array#exclude?を実行する

```ruby
% goby -i
Goby 0.1.3 🤥 😗 😗
» [].methods
#» ["*", "+", "[]", "[]=", "any?", "at", "clear", "concat", "count", "delete_at", "dig", "each", "each_index", "empty?", "exclude?", "first", "flatten", "include?", "join", "last", "length", "map", "new", "pop", "push", "reduce", "reject", "reverse", "reverse_each", "rotate", "select", "shift", "unshift", "values_at", "!", "!=", "==", "block_given?", "class", "instance_variable_get", "instance_variable_set", "is_a?", "methods", "nil?", "object_id", "puts", "require", "require_relative", "send", "singleton_class", "sleep", "thread", "to_s"]
» [].methods.include?('exclude?')
#» true
» [].methods.exclude?('include?')
#» false
```