Adds reduce tot he std lib

This commit is contained in:
sloum 2022-05-24 14:05:46 -07:00
parent 19c90cd43b
commit 8ca1c6465b
4 changed files with 27 additions and 6 deletions

View File

@ -268,7 +268,7 @@ So...
Implemented:
`length`, `cons`, `car`, `cdr`, `append`, `list`, `map`, `for-each`, `list->string`, `ref`, `list-sort`, `reverse`, `assoc`, `member?`, `slice`, `list-seed`, `list-join`
`length`, `cons`, `car`, `cdr`, `append`, `list`, `map`, `for-each`, `list->string`, `ref`, `list-sort`, `reverse`, `assoc`, `member?`, `slice`, `list-seed`, `list-join`, `reduce`
- `list` can be shorthanded by using square brackets: `[1 2 3]` vs `(list 1 2 3)`
- `length` and `reverse` will take a string or a list.
@ -291,6 +291,7 @@ Implemented:
<li><code>(list->string [list] [join-on: string])</code>: <code>string</code></li>
<li><code>(ref [list|string] [index: number] [[set: value]])</code>: <code>value|list|string</code></li>
<li><code>(list-sort [list] [[sub-list-index: number]])</code>: <code>list</code></li>
<li><code>(reduce [procedure] [accumulator: value] [list])</code>: <code>value</code></li>
<li><code>(reverse [list|string])</code>: <code>list</code></li>
<li><code>(slice [list|string] [number] [[number]])</code>: <code>list|string</code></li>
<li><code>(assoc [assoc-list] [key: value] [[value: value]])</code>: <code>value</code></li>

19
lib.go
View File

@ -964,6 +964,25 @@ var stdLibrary = vars{
return exception("map expects a procedure followed by at least one list")
}
},
"reduce": func(a ...expression) expression {
if len(a) < 3 {
return exception("'reduce' expects a procedure followed by an initializer value and a list, too few arguments given")
}
switch p := a[0].(type) {
case proc, func(...expression) expression:
init := a[1]
list, ok := a[2].([]expression)
if !ok {
return exception("'reduce' expects a list as its third argument, a non-list value was given")
}
for i := range list {
init = apply(p, []expression{list[i], init})
}
return init
default:
return exception("'reduce' expects a procedure as its first argument, a non-procedure value was given")
}
},
"for-each": func(a ...expression) expression {
if len(a) < 2 {
return exception("for-each expects a procedure followed by at least one list")

View File

@ -16,7 +16,7 @@ import (
ln "github.com/peterh/liner"
)
const version = "0.5.19"
const version = "0.6.0"
const globalLibPath = "/usr/local/lib/slope/modules/"

View File

@ -122,10 +122,11 @@ var usageStrings = map[string]string{
"pwd": "(pwd) => string\n\nReturns the current working directory as a string",
"quote": "(quote [expression...]) => bool",
"rand": "(rand [[max]] [[min]]) => number\n\nIf no arguments are given `rand` will produce a floating point number between 0 and 1. If only `max` is given, `rand` will produce a floating point number between 0 and `max`. If `max` and `min` are both given, `rand` will produce a floating point number between `min` and `max`. `max` is always exclusive (the value produced will always be less than `max`), while `min` is inclusize. To obtain integers use `floor`, `ceil`, or `round` on the result or `rand`",
"read-all": "(read-all [[IOHandle]]) => string",
"read-all-lines": "(read-all-lines [[IOHandle]]) => list",
"read-char": "(read-char [[IOHandle]]) => string|#f",
"read-line": "(read-line [[IOHandle]]) => string|#f",
"read-all": "(read-all [[IOHandle]]) => string\n\nReads all content from the given io-handle",
"read-all-lines": "(read-all-lines [[IOHandle]]) => list\n\nReads all content from the given io-handle and splits it into a list on newline",
"read-char": "(read-char [[IOHandle]]) => string|#f\n\nReads a rune from the given io-handle. Does not opperate on string buffers",
"read-line": "(read-line [[IOHandle]]) => string|#f\n\nReads a line from the given io-handle. 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",
"regex-find": "(regex-find [pattern: string] [string]) => list",
"regex-match?": "(regex-match? [pattern: string] [string]) => bool",