Merge branch 'relative-lists' into bytes

This commit is contained in:
sloum 2022-07-09 13:35:06 -07:00
commit 834e2b19f3
2 changed files with 36 additions and 17 deletions

49
lib.go
View File

@ -605,19 +605,35 @@ var stdLibrary = vars{
}
if reflect.DeepEqual(l[0], a[1]) {
if len(a) >= 3 {
cpy := make([]expression, len(list))
copy(cpy, list)
cpy[x] = []expression{l[0], a[2]}
return cpy
if len(a) > 3 && AnythingToBool(a[3]).(bool) {
l[1] = a[2]
list[x] = l
return list
} else {
cpy := make([]expression, len(list))
copy(cpy, list)
cpy[x] = []expression{l[0], a[2]}
return cpy
}
}
return l[1]
}
}
if len(a) >= 3 {
cpy := make([]expression, len(list))
copy(cpy, list)
cpy = append(cpy, []expression{a[1], a[2]})
return cpy
if len(a) > 3 && AnythingToBool(a[3]).(bool) {
// This will almost certainly create a new assoc
// and return it rather than adding to the existing
// assoc, and is thus similar to the else branch,
// but in theory has a chance that a copy will not
// be needed, thus potentially executing faster.
list = append(list, []expression{a[1], a[2]})
return list
} else {
cpy := make([]expression, len(list))
copy(cpy, list)
cpy = append(cpy, []expression{a[1], a[2]})
return cpy
}
}
return exception("'assoc' could not find the key: " + String(a[1], true))
},
@ -1046,9 +1062,7 @@ var stdLibrary = vars{
}
switch base := a[0].(type) {
case []expression:
for _, v := range a[1:] {
base = append(base, v)
}
base = append(base, a[1:]...)
return base
default:
var out strings.Builder
@ -1075,10 +1089,15 @@ var stdLibrary = vars{
return exception("'ref' was given an index number that is out of bounds for the given list")
}
if len(a) >= 3 {
cpy := make([]expression, len(v))
copy(cpy, v)
cpy[int(i)] = a[2]
return cpy
if len(a) > 3 && AnythingToBool(a[3]).(bool) {
v[int(i)] = a[2]
return v
} else {
cpy := make([]expression, len(v))
copy(cpy, v)
cpy[int(i)] = a[2]
return cpy
}
}
return v[int(i)]
case string:

View File

@ -40,7 +40,7 @@ var usageStrings = map[string]string{
"and": "(and [expression...]) => bool\n\nChecks the truthiness of all expressions passed to it. If any expression is falsy then false is returned and no further expressions are checked; otherwise returns true",
"append": "(append [list|value] [[value...]]) => list|string\n\nAdds the given value(s) to the end of the given list|string. If a list alone is given it is simply returned. If a single value is given it will be coerced to string and returned. If multiple values are given they will be concatenated and a string will be returned; any non-string values will be coerced to string before concatenation",
"apply": "(apply [procedure] [arguments: list]) => value\n\nSpreads the list values as arguments to the given procedure. This results in behavior where the following two examples are equivalent:\n\n\t(+ 1 2 3)\n\t(apply + [1 2 3])",
"assoc": "(assoc [association-list] [key: value] [[value]]) => value|list\n\nIf two arguments are given then `assoc` retrieves the value of the key. If a third argument is given `assoc` will set the value for the given key to the given value, returning the updated list",
"assoc": "(assoc [association-list] [key: value] [[value]] [[relative?: bool]]) => value|list\n\nIf two arguments are given then `assoc` retrieves the value of the key. If a third argument is given `assoc` will set the value for the given key to the given value, returning the updated list. If `relative?` is `#t` and an existing field is gettings set, it will be set in place via relative reference. This does not reliably function for adding a new key to the association and you should always store the new association with `set!` when adding a new key. However, execution may be faster with `relative?` set due to optimizations that can potentially exist in the underlying implementation",
"assoc?": "(assoc? [value]) => bool\n\nDetermines whether or not the given value is an association list",
"atom?": "(atom? [value]) => bool\n\nDetermines whether a given value is atomic (in practice this mostly works out to: not a list)",
"begin": "(begin [expression...]) => value\n\nEvaluates a series of expressions and returns the value of the last expression that is evaluated",
@ -147,7 +147,7 @@ var usageStrings = map[string]string{
"read-char": "(read-char [[io-handle]]) => string|#f\n\nReads a rune from the given io-handle (defaulting to stdin). Does not opperate on string buffers",
"read-line": "(read-line [[io-handle]]) => string|#f\n\nReads a line from the given io-handle (defaulting to stdin). Does not opperate on string buffers",
"reduce": "(reduce [procedure] [accumulator: value] [list]) => value\n\nThe given procedure should always take two values: the current list item and the current state of the accumulator. The procedure should return the accumulator state for the next evaluation of the procedure (ie. with the next list item). You do not need to bounds check within the procedure, it will be run once for every item in the list. The accumulator can be of any type and can, in theory, change type over the course of running reduce. The list can contain any values that the procedure is able to work with.\n\nExample:\n\n\t(reduce + 0 [1 2 3 4 5])\n\nReturns:\n\n\t15",
"ref": "(ref [list|string] [index: number] [[set: value]]) => value|list|string\n\nList/string indexing starts at 0. When the optional `set` argument is provided the list/string will be returned with the value at the given index replaced by the `set` value that was given. Any value given as the optional set argument when working with a string will be coerced to a string, if an empty string is given then the index will be removed from the string",
"ref": "(ref [list|string] [index: number] [[set: value]] [[relative?: bool]]) => value|list|string\n\nList/string indexing starts at 0. When the optional `set` argument is provided the list/string will be returned with the value at the given index replaced by the `set` value that was given. Any value given as the optional set argument when working with a string will be coerced to a string, if an empty string is given then the index will be removed from the string. If a list is given along with an index, set value, and relative? is true, the value will be updated in place without need to store the list again with `set!`. `relative?` does not affect strings",
"regex-find": "(regex-find [pattern: string] [string]) => list",
"regex-match?": "(regex-match? [pattern: string] [string]) => bool",
"regex-replace": "(regex-replace [pattern: string] [input: string] [replacement: string]) => string",