Introduction to Scheme: Difference between revisions
(Created page with "When you run <code>./memcp</code>, you will be dropped at a scheme shell like this: memcp Copyright (C) 2023, 2024 Carl-Philip Hänsch This program comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to redistribute it under certain conditions; loading storage /tmp/x/system/bdf64a22-6315-463c-bbf7-329317ad50ed-id of type 10 loading storage /tmp/x/system/bdf64a22-6315-463c-bbf7-329317ad50ed-username of type 20 loading stora...") |
No edit summary |
||
Line 29: | Line 29: | ||
> 12 | > 12 | ||
= 12 | = 12 | ||
> "hi" | > "hi" | ||
= "hi" | = "hi" | ||
> (+ 1 2) | > (+ 1 2) | ||
= 3 | = 3 | ||
> (+ 1 2 3) | > (+ 1 2 3) | ||
= 6 | = 6 | ||
> (+ 2 (* 2 2)) | > (+ 2 (* 2 2)) | ||
= 6 | = 6 | ||
> (+ 2 (* 2 4)) | > (+ 2 (* 2 4)) | ||
= 10 | = 10 | ||
> (concat "Hello" "World") | > (concat "Hello" "World") | ||
= "HelloWorld" | = "HelloWorld" | ||
Line 69: | Line 75: | ||
= 4 | = 4 | ||
Lambda functions can be passed to other functions as values. They enclose your original scope, so you can use variables from the outside inside your function. | Lambda functions can be passed to other functions as values. They enclose your original scope, so you can use variables from the outside inside your function. | ||
== List handling == | |||
The following list functions can be used: | |||
> '(1 2 3) "list literal" | |||
= (1 2 3) | |||
> (cons 0 '(1 2 3)) "prepend item to list" | |||
= (0 1 2 3) | |||
> (append '(1 2 3) 4 5) "append items to list" | |||
= (1 2 3 4 5) | |||
> (has? '(1 2 3) 2) "check if item is in list" | |||
= true | |||
> (filter '(1 2 3) (lambda (x) (< x 2))) "filter items that are smaller than 2" | |||
= (1) | |||
> (map '(1 2 3) (lambda (x) (* x 2))) "double all numbers" | |||
= (2 4 6) | |||
> (reduce '(1 2 3) + 0) "build sum by starting with 0 and reducing them over (+ 0 value)" | |||
= 6 | |||
== Associative Lists (Objects) == | |||
The following functions can be used: | |||
> (set obj '("a" 1 "b" 2 "c" 3)) /* construct object from a list with alternating key-value */ | |||
= ("a" 1 "b" 2 "c" 3) | |||
> (obj "a") /* extract a value */ | |||
= 1 | |||
> (set_assoc obj "a" "5") /* construct a new object with another value */ | |||
= ("a" "5" "b" 2 "c" 3) | |||
> (set obj (set_assoc obj "a" "5")) /* modify obj */ | |||
= ("a" "5" "b" 2 "c" 3) | |||
> (filter_assoc obj (lambda (key value) (not (equal? key "c")))) /* filter an object by a condition */ | |||
= ("a" 1 "b" 2) | |||
> (map_assoc obj (lambda (key value) (* value 2))) /* double all values */ | |||
= ("a" 2 "b" 4 "c" 6) | |||
> (reduce_assoc obj (lambda (accumulator key value) (+ accumulator value)) 0) /* sum up all values */ | |||
= 6 | |||
As you see in <code>set_assoc</code>, we have a pure functional approach here. Objects are not modified in-place like in languages like Java, JavaScript, Python, C++ or such, but rather we have to construct a modified copy of that value and overwrite it to the original value. The Scheme optimizer will detect if an in-place operation would be safe, too and can optimize this corner case but the language itself prioritizes safety. | |||
== Further Help and Documentation of all Functions == | == Further Help and Documentation of all Functions == |
Revision as of 15:24, 17 May 2024
When you run ./memcp
, you will be dropped at a scheme shell like this:
memcp Copyright (C) 2023, 2024 Carl-Philip Hänsch This program comes with ABSOLUTELY NO WARRANTY; This is free software, and you are welcome to redistribute it under certain conditions; loading storage /tmp/x/system/bdf64a22-6315-463c-bbf7-329317ad50ed-id of type 10 loading storage /tmp/x/system/bdf64a22-6315-463c-bbf7-329317ad50ed-username of type 20 loading storage /tmp/x/system/bdf64a22-6315-463c-bbf7-329317ad50ed-password of type 20 Welcome to memcp performing unit tests ... finished unit tests test result: 15/15 all tests succeeded. Initializing SQL frontend MySQL server listening on port 3307 (connect with `mysql -P 3307 -u root -p` using password 'admin') listening on http://localhost:4321 Type (help) to show help >
Scheme is a functional programming language and a subset of LISP. Every expression is either a primitive value or a list.
To understand the semantics of Scheme, take a look at the following Scheme REPL session:
> 12 = 12 > "hi" = "hi" > (+ 1 2) = 3 > (+ 1 2 3) = 6 > (+ 2 (* 2 2)) = 6 > (+ 2 (* 2 4)) = 10 > (concat "Hello" "World") = "HelloWorld"
Syntax
Function Call
A function call has the following format:
(functionname param1 param2 param3 ...)
Function calls start with (
, contain one function and zero or more parameters separated by space .
Some basic functions are + - * / print concat
. For more consult the manual with (help)
.
Literals
The following literals are allowed:
- Number Literals:
1 2 3 56 7.5 4.3e20 -6.123e-3
- String Literals:
"Hello World" "First Line\nSecond Line" "he said: \"what?\" and smiled"
- Function names:
print
- Symbol literals
'print
- List literals
'(1 2 3) '("a" "b" "c")
- Associative Array literals
'("key" "value" "size" 45 "name" "Peter" "sublist" '(1 2 3))
- associative arrays are lists with key value pairs flattened down to a one dimensional list of an even number of items. - Lambdas:
(lambda (param1 param2 ...) body)
Lambda Functions
Scheme allows for creating lambda functions which enclose their own scope:
(define decrease-by-one (lambda (number) (- number 1)))
The function can now be called from scheme:
> (decrease-by-one 5) = 4
Lambda functions can be passed to other functions as values. They enclose your original scope, so you can use variables from the outside inside your function.
List handling
The following list functions can be used:
> '(1 2 3) "list literal" = (1 2 3) > (cons 0 '(1 2 3)) "prepend item to list" = (0 1 2 3) > (append '(1 2 3) 4 5) "append items to list" = (1 2 3 4 5) > (has? '(1 2 3) 2) "check if item is in list" = true > (filter '(1 2 3) (lambda (x) (< x 2))) "filter items that are smaller than 2" = (1) > (map '(1 2 3) (lambda (x) (* x 2))) "double all numbers" = (2 4 6) > (reduce '(1 2 3) + 0) "build sum by starting with 0 and reducing them over (+ 0 value)" = 6
Associative Lists (Objects)
The following functions can be used:
> (set obj '("a" 1 "b" 2 "c" 3)) /* construct object from a list with alternating key-value */ = ("a" 1 "b" 2 "c" 3) > (obj "a") /* extract a value */ = 1 > (set_assoc obj "a" "5") /* construct a new object with another value */ = ("a" "5" "b" 2 "c" 3) > (set obj (set_assoc obj "a" "5")) /* modify obj */ = ("a" "5" "b" 2 "c" 3) > (filter_assoc obj (lambda (key value) (not (equal? key "c")))) /* filter an object by a condition */ = ("a" 1 "b" 2) > (map_assoc obj (lambda (key value) (* value 2))) /* double all values */ = ("a" 2 "b" 4 "c" 6) > (reduce_assoc obj (lambda (accumulator key value) (+ accumulator value)) 0) /* sum up all values */ = 6
As you see in set_assoc
, we have a pure functional approach here. Objects are not modified in-place like in languages like Java, JavaScript, Python, C++ or such, but rather we have to construct a modified copy of that value and overwrite it to the original value. The Scheme optimizer will detect if an in-place operation would be safe, too and can optimize this corner case but the language itself prioritizes safety.
Further Help and Documentation of all Functions
If you type (help)
into the console, you will get the following overview:
> (help) Available scm functions: -- SCM Builtins -- quote: returns a symbol or list without evaluating it eval: executes the given scheme program in the current environment optimize: optimize the given scheme program if: checks a condition and then conditionally evaluates code branches; there might be multiple condition+true-branch clauses and: returns true if all conditions evaluate to true or: returns true if at least one condition evaluates to true coalesce: returns the first value that has a non-zero value coalesceNil: returns the first value that has a non-nil value define: defines or sets a variable in the current environment set: defines or sets a variable in the current environment error: halts the whole execution thread and throws an error message try: tries to execute a function and returns its result. In case of a failure, the error is fed to the second function and its result value will be used apply: runs the function with its arguments apply_assoc: runs the function with its arguments but arguments is a assoc list symbol: returns a symbol built from that string list: returns a list containing the parameters as alements string: converts the given value into string match: takes a value evaluates the branch that first matches the given pattern lambda: returns a function (func) constructed from the given code begin: creates a own variable scope, evaluates all sub expressions and returns the result of the last one parallel: executes all parameters in parallel and returns nil if they are finished source: annotates the node with filename and line information for better backtraces -- Arithmetic / Logic -- number?: tells if the value is a number +: adds two or more numbers -: subtracts two or more numbers from the first one *: multiplies two or more numbers /: divides two or more numbers from the first one <=: compares two numbers <: compares two numbers >: compares two numbers >=: compares two numbers equal?: deep-compares two values of the same type equal??: performs a sloppy equality check on primitive values (number, string, bool. nil), strings are compared case insensitive !: negates the boolean value not: negates the boolean value nil?: returns true if value is nil min: returns the smallest value max: returns the highest value floor: rounds the number down ceil: rounds the number up round: rounds the number -- Strings -- string?: tells if the value is a string concat: concatenates stringable values and returns a string substr: returns a substring simplify: turns a stringable input value in the easiest-most value (e.g. turn strings into numbers if they are numeric strlen: returns the length of a string strlike: matches the string against a wildcard pattern (SQL compliant) toLower: turns a string into lower case toUpper: turns a string into upper case replace: replaces all occurances in a string with another string split: splits a string using a separator or space htmlentities: escapes the string for use in HTML urlencode: encodes a string according to URI coding schema urldecode: decodes a string according to URI coding schema -- Lists -- append: appends items to a list and return the extended list. append_unique: appends items to a list but only if they are new. cons: constructs a list from a head and a tail list car: extracts the head of a list cdr: extracts the tail of a list merge: flattens a list of lists into a list containing all the subitems. If one parameter is given, it is a list of lists that is flattened. If multiple parameters are given, they are treated as lists that will be merged into one merge_unique: flattens a list of lists into a list containing all the subitems. Duplicates are filtered out. has?: checks if a list has a certain item (equal?) filter: returns a list that only contains elements that pass the filter function map: returns a list that contains the results of a map function that is applied to the list mapIndex: returns a list that contains the results of a map function that is applied to the list reduce: returns a list that contains the result of a map function produce: returns a list that contains produced items - it works like for(state = startstate, condition(state), state = iterator(state)) {yield state} produceN: returns a list with numbers from 0..n-1 list?: checks if a value is a list contains?: checks if a value is in a list; uses the equal?? operator -- Associative Lists / Dictionaries -- filter_assoc: returns a filtered dictionary according to a filter function map_assoc: returns a mapped dictionary according to a map function reduce_assoc: reduces a dictionary according to a reduce function has_assoc?: checks if a dictionary has a key present extract_assoc: applies a function (key value) on the dictionary and returns the results as a flat list set_assoc: returns a dictionary where a single value has been changed. merge_assoc: returns a dictionary where all keys from dict1 and all keys from dict2 are present. -- Parsers -- parser: creates a parser -- Sync -- newsession: Creates a new session which is a threadsafe key-value store represented as a function that can be either called as a getter (session key) or setter (session key value) or list all keys with (session) once: Creates a function wrapper that you can call multiple times but only gets executed once. The result value is cached and returned on a second call. You can add parameters to that resulting function that will be passed to the first run of the wrapped function. mutex: Creates a mutex. The return value is a function that takes one parameter which is a parameterless function. The mutex is guaranteed that all calls to that mutex get serialized. -- IO -- print: Prints values to stdout (only in IO environment) help: Lists all functions or print help for a specific function import: Imports a file .scm file into current namespace load: Loads a file and returns the string serve: Opens a HTTP server at a given port mysql: Imports a file .scm file into current namespace password: Hashes a password with sha1 (for mysql user authentication) -- Storage -- scan: does an unordered parallel filter-map-reduce pass on a single table and returns the reduced result scan_order: does an ordered parallel filter and serial map-reduce pass on a single table and returns the reduced result createdatabase: creates a new database dropdatabase: creates a new database createtable: creates a new database createcolumn: creates a new column in table shardcolumn: tells us how it would partition a column according to their values. Returns a list of pivot elements. altertable: alters a table droptable: removes a table insert: inserts a new dataset into table stat: return memory statistics show: show databases/tables/columns rebuild: rebuilds all main storages and returns the amount of time it took loadCSV: loads a CSV file into a table and returns the amount of time it took. loadJSON: loads a .jsonl file from disk into a database and returns the amount of time it took. settings: reads or writes a global settings value. This modifies your data/settings.json. get further information by typing (help "functionname") to get more info