Преглед изворни кода

Adding Built-in Functions for Arrays
1. first
2. last
3. rest
4. push

runningwater пре 3 година
родитељ
комит
3dd0da1fa4
1 измењених фајлова са 90 додато и 0 уклоњено
  1. 90 0
      evaluator/builtins.go

+ 90 - 0
evaluator/builtins.go

@@ -19,4 +19,94 @@ var builtins = map[string]*object.Builtin{
 			}
 		},
 	},
+	"first": {
+		Fn: func(args ...object.Object) object.Object {
+			if len(args) != 1 {
+				return newError("wrong number of arguments. got=%d, want=1", len(args))
+			}
+			if args[0].Type() != object.ArrayObj {
+				return newError("argument to `first` must be ARRAY, got %s", args[0].Type())
+			}
+			arr := args[0].(*object.Array)
+			if len(arr.Elements) > 0 {
+				return arr.Elements[0]
+			}
+			return NULL
+		},
+	},
+	"last": {
+		Fn: func(args ...object.Object) object.Object {
+			if len(args) != 1 {
+				return newError("wrong number of arguments. got=%d, want=1", len(args))
+			}
+			if args[0].Type() != object.ArrayObj {
+				return newError("argument to `first` must be ARRAY, got %s", args[0].Type())
+			}
+
+			arr := args[0].(*object.Array)
+			length := len(arr.Elements)
+			if length > 0 {
+				return arr.Elements[length-1]
+			}
+			return NULL
+		},
+	},
+	// rest returns a new array containing all elements of the array passed as argument, except the first one
+	// >> let a = [1, 2, 3, 4];
+	// >> rest(a)
+	// [2, 3, 4]
+	// >> rest(rest(a))
+	// [3, 4]
+	// >> rest(rest(rest(a)))
+	// [4]
+	// >> rest(rest(rest(rest(a))))
+	// []
+	// >> rest(rest(rest(rest(rest(a)))))
+	// null
+	"rest": {
+		Fn: func(args ...object.Object) object.Object {
+			if len(args) != 1 {
+				return newError("wrong number of arguments. got=%d, want=1", len(args))
+			}
+			if args[0].Type() != object.ArrayObj {
+				return newError("argument to `first` must be ARRAY, got %s", args[0].Type())
+			}
+
+			arr := args[0].(*object.Array)
+			length := len(arr.Elements)
+			if length > 0 {
+				newElements := make([]object.Object, length-1, length-1)
+				copy(newElements, arr.Elements[1:length])
+				return &object.Array{Elements: newElements}
+			}
+			return NULL
+		},
+	},
+	// It adds a new element to the end of the array. But, and here's the kicker, it doesn't modify the given array.
+	// Instead, it allocates a new array with the same elements as the old one plus the new, pushed element.
+	// >> let a = [1, 2, 3, 4];
+	// >> let b = push(a, 5);
+	// >> a
+	//[1, 2, 3, 4]
+	// >> b
+	//[1, 2, 3, 4, 5]
+	"push": {
+		Fn: func(args ...object.Object) object.Object {
+			if len(args) != 2 {
+				return newError("wrong number of arguments. got=%d, want=1", len(args))
+			}
+			if args[0].Type() != object.ArrayObj {
+				return newError("argument to `first` must be ARRAY, got %s", args[0].Type())
+			}
+
+			arr := args[0].(*object.Array)
+			length := len(arr.Elements)
+
+			newElements := make([]object.Object, length+1, length+1)
+			copy(newElements, arr.Elements)
+			newElements[length] = args[1]
+
+			return &object.Array{Elements: newElements}
+		},
+	},
 }