diff --git a/404.html b/404.html index 32fab604..b909f00a 100644 --- a/404.html +++ b/404.html @@ -4,7 +4,7 @@ Page Not Found | LIPS Scheme - + diff --git a/assets/js/413466e5.4bfa6453.js b/assets/js/413466e5.4bfa6453.js new file mode 100644 index 00000000..784b434c --- /dev/null +++ b/assets/js/413466e5.4bfa6453.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[8649],{1977:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>t,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"scheme-intro/core","title":"Core of Scheme","description":"Main article that shows most of the features of Scheme","source":"@site/docs/scheme-intro/core.md","sourceDirName":"scheme-intro","slug":"/scheme-intro/core","permalink":"/docs/scheme-intro/core","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/scheme-intro/core.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"sidebar_position":3,"description":"Main article that shows most of the features of Scheme"},"sidebar":"tutorialSidebar","previous":{"title":"Data Types","permalink":"/docs/scheme-intro/data-types"},"next":{"title":"Input and Output","permalink":"/docs/scheme-intro/input-output"}}');var r=s(4848),l=s(8453);const a={sidebar_position:3,description:"Main article that shows most of the features of Scheme"},c="Core of Scheme",t={},d=[{value:"Printing values",id:"printing-values",level:2},{value:"Math expressions",id:"math-expressions",level:2},{value:"Boolean expression",id:"boolean-expression",level:3},{value:"Functions that returns part of the number",id:"functions-that-returns-part-of-the-number",level:3},{value:"Predicates",id:"predicates",level:2},{value:"Equal operation",id:"equal-operation",level:3},{value:"String and character comparators",id:"string-and-character-comparators",level:3},{value:"Symbols",id:"symbols",level:3},{value:"Type Predicates",id:"type-predicates",level:3},{value:"Variables",id:"variables",level:2},{value:"Modification of the variable",id:"modification-of-the-variable",level:3},{value:"Local variables",id:"local-variables",level:2},{value:"Conditionals",id:"conditionals",level:2},{value:"Boolean expressions",id:"boolean-expressions",level:2},{value:"Procedures",id:"procedures",level:2},{value:"Nested Procedures",id:"nested-procedures",level:3},{value:"Immediately invoked lambda",id:"immediately-invoked-lambda",level:3},{value:"Variable number of arguments",id:"variable-number-of-arguments",level:3},{value:"Optional arguments",id:"optional-arguments",level:3},{value:"Recursion",id:"recursion",level:3},{value:"Local Recursive Functions",id:"local-recursive-functions",level:4},{value:"Tail Call Optimization",id:"tail-call-optimization",level:3},{value:"Loops",id:"loops",level:2},{value:"List operations",id:"list-operations",level:2},{value:"Iterating over a list recursively",id:"iterating-over-a-list-recursively",level:3},{value:"Alists",id:"alists",level:3},{value:"Finding element in the list",id:"finding-element-in-the-list",level:2},{value:"Vector operations",id:"vector-operations",level:2},{value:"String operations",id:"string-operations",level:2},{value:"Multiple values",id:"multiple-values",level:2},{value:"Higher order functions",id:"higher-order-functions",level:2},{value:"Closures",id:"closures",level:2},{value:"Objects",id:"objects",level:2},{value:"Records",id:"records",level:3},{value:"Dynamic variables",id:"dynamic-variables",level:2},{value:"Loading of external code",id:"loading-of-external-code",level:2},{value:"Eval",id:"eval",level:2},{value:"Scheme libraries",id:"scheme-libraries",level:2},{value:"Portable code",id:"portable-code",level:2}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"core-of-scheme",children:"Core of Scheme"})}),"\n",(0,r.jsx)(n.h2,{id:"printing-values",children:"Printing values"}),"\n",(0,r.jsx)(n.p,{children:"To print a value, you can use two type of expressions:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(display "hello")\n;; ==> hello\n'})}),"\n",(0,r.jsx)(n.p,{children:"and"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(write "hello")\n;; ==> "hello"\n'})}),"\n",(0,r.jsx)(n.p,{children:"The first will print text hello without quotations. But the second will include the quotes. The\nsecond expression allows saving the expression and later read it as Scheme code."}),"\n",(0,r.jsx)(n.p,{children:"Both expression don't add newline at the end. To add a newline, you need to use:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(newline)\n"})}),"\n",(0,r.jsx)(n.p,{children:"Or you can use escape newline character:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(display "\\n")\n'})}),"\n",(0,r.jsx)(n.h2,{id:"math-expressions",children:"Math expressions"}),"\n",(0,r.jsx)(n.p,{children:"Scheme defines standard Math operations:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"+"})," - sum all its arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"-"})," - subtract the arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"/"})," - divide the arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"*"})," - multiply the arguments"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"All the above can accept zero or more arguments."}),"\n",(0,r.jsx)(n.p,{children:"Trigonometry functions:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"sin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"cos"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"tan"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"asin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"acos"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"atan"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"logarithms:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"log"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Exponentiation function:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"expt"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Exponential function"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"exp"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"It also defines:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"square"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"sqrt"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"boolean-expression",children:"Boolean expression"}),"\n",(0,r.jsxs)(n.p,{children:["Expressions that returns ",(0,r.jsx)(n.code,{children:"true"})," or ",(0,r.jsx)(n.code,{children:"false"})," and operate on numbers"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"<"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:">"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"<="})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:">="})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"="})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"functions-that-returns-part-of-the-number",children:"Functions that returns part of the number"}),"\n",(0,r.jsx)(n.p,{children:"Rational and complex numbers are created from two different numbers."}),"\n",(0,r.jsx)(n.p,{children:"Rational numbers are created from numerator and denominator, and you can get those numbers from a single rational:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(numerator 1/2)\n;; ==> 1\n(denominator 1/2)\n;; ==> 2\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"NOTE:"})," The result values of those expressions are written as comments."]}),"\n",(0,r.jsx)(n.p,{children:"Complex numbers are created with real and imaginary parts, and you can also extract those parts:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(imag-part 10+2i)\n;; ==> 2\n(real-part 10+2i)\n;; ==> 10\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Scheme also define two functions ",(0,r.jsx)(n.code,{children:"angle"})," and ",(0,r.jsx)(n.code,{children:"magnitude"})," which can be used to get modulus and argument."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(angle 10+10i)\n;; ==> 0.7853981633974483\n(magnitude 10+10i)\n;; ==> 14.142135623730951\n"})}),"\n",(0,r.jsx)(n.h2,{id:"predicates",children:"Predicates"}),"\n",(0,r.jsx)(n.h3,{id:"equal-operation",children:"Equal operation"}),"\n",(0,r.jsx)(n.p,{children:"In Scheme there are a different way to compare values:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"eq?"})," - compares if the values are the same object works only on basic types"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"eqv?"})," - compares if the values have the same representation"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"equal?"})," - also works any type of values, it can compare vectors and list if they are the same"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"string-and-character-comparators",children:"String and character comparators"}),"\n",(0,r.jsx)(n.p,{children:"In addition, there are also comparators for strings:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"characters:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"String and characters also have counterpart procedures for compare with case-insensitive way:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"characters:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"symbols",children:"Symbols"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"symbol=?"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"type-predicates",children:"Type Predicates"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"pair?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"list?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"null?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"symbol?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"boolean?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"number?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"integer?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"complex?"})}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"variables",children:"Variables"}),"\n",(0,r.jsxs)(n.p,{children:["To define a variable in Scheme you use ",(0,r.jsx)(n.code,{children:"define"})," special form:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define number 10)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This will define variable ",(0,r.jsx)(n.code,{children:"number"})," with value 10. You can evaluate this variable and get the value back."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"number\n"})}),"\n",(0,r.jsx)(n.p,{children:"This will evaluate to 10. Note that this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"'number\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Will evaluate into symbol ",(0,r.jsx)(n.code,{children:"number"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"modification-of-the-variable",children:"Modification of the variable"}),"\n",(0,r.jsxs)(n.p,{children:["To modify (mutate) existing variable, you use ",(0,r.jsx)(n.code,{children:"set!"})," procedure. There is a conversion of using exclamation\nmark for destructive type of procedure. Which are procedures that modify its arguments."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define number 10)\n(set! number (+ number 1))\n(display number)\n;; ==> 11\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In the above expression, the number is increased by ",(0,r.jsx)(n.code,{children:"1"}),". The number in ",(0,r.jsx)(n.code,{children:"(+ number 1)"})," reference old value\nof the variable. And ",(0,r.jsx)(n.code,{children:"set!"})," special form update the variable with new value."]}),"\n",(0,r.jsx)(n.h2,{id:"local-variables",children:"Local variables"}),"\n",(0,r.jsxs)(n.p,{children:["You can create local variables with ",(0,r.jsx)(n.code,{children:"let"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x 10) (y 20))\n (+ x y))\n;; ==> 30\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This will create two variables ",(0,r.jsx)(n.code,{children:"x"})," and ",(0,r.jsx)(n.code,{children:"y"})," with values ",(0,r.jsx)(n.code,{children:"10"})," and ",(0,r.jsx)(n.code,{children:"20"})," respectively and sum those with\nplus procedure."]}),"\n",(0,r.jsxs)(n.p,{children:["There is also additional ",(0,r.jsx)(n.code,{children:"let*"})," expression that allow to return previous value in next expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let* ((x 10) (y (* x x)))\n (+ x y))\n;; ==> 110\n"})}),"\n",(0,r.jsxs)(n.p,{children:["And ",(0,r.jsx)(n.code,{children:"letrec"})," that allows to create local recursive functions (allow reference same binding):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(letrec ((sum (lambda (list)\n (if (null? list)\n 0\n (+ (car list) (sum (cdr list)))))))\n (sum '(1 2 3 4)))\n;; ==> 10\n"})}),"\n",(0,r.jsx)(n.h2,{id:"conditionals",children:"Conditionals"}),"\n",(0,r.jsxs)(n.p,{children:["In Scheme there are 3 ways to define conditionals. The basic expression is ",(0,r.jsx)(n.code,{children:"if"})," statement."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (< 1 2)\n (write "this is true")\n (write "this is false"))\n'})}),"\n",(0,r.jsx)(n.p,{children:"If you need to put more than one expression inside if statement (or any other expression that\nexpect single expression) you can use begin:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (< 1 2)\n (begin\n (write "this is true")\n (newline)))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsx)(n.p,{children:"The else part is optional."}),"\n",(0,r.jsxs)(n.p,{children:["You also have a shortcut for this case in ",(0,r.jsx)(n.code,{children:"when"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(when (< 1 2)\n (write "this is true")\n (newline))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["There is also create the opposite with ",(0,r.jsx)(n.code,{children:"unless"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(unless #f\n (write "this is true")\n (newline))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"cond"})," is another expression that allow to add multiple conditions:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(cond ((< 2 2) (write "first"))\n ((< 2 1) (write "second"))\n (else\n (write "other")))\n;; ==> "other"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["The first two expressions return false, so ",(0,r.jsx)(n.code,{children:"cond"})," will evaluate the ",(0,r.jsx)(n.code,{children:"else"})," condition and display ",(0,r.jsx)(n.code,{children:'"other"'}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Case is the last of basic condition expressions. It allows checking given expression is one of the given values."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(let ((x \'foo))\n (case x\n ((one two) (display "first"))\n ((foo bar) (display "second"))\n (else\n (display "other"))))\n;; ==> second\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Symbol foo is of the second list, so this expression will print ",(0,r.jsx)(n.code,{children:'"second"'}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"boolean-expressions",children:"Boolean expressions"}),"\n",(0,r.jsx)(n.p,{children:"Scheme provide 3 boolean special forms that can be used to combine other expressions:"}),"\n",(0,r.jsxs)(n.p,{children:["They are not functions but special forms that can be used to create ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Short-circuit_evaluation",children:"Short-circuit\nevaluation"})," also called McCarthy evaluation\nfrom ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/John_McCarthy_(computer_scientist)",children:"John McCarthy"})," inventor of\nLisp."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"and"})," - returns ",(0,r.jsx)(n.code,{children:"true"})," when all elements are true value (in Scheme all values are true except ",(0,r.jsx)(n.code,{children:"#f"}),"),\nand stop evaluates when it finds ",(0,r.jsx)(n.code,{children:"#f"})]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (and (< 1 2) (> 3 1))\n (display "true"))\n;; ==> true\n'})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"or"})," - returns ",(0,r.jsx)(n.code,{children:"#f"})," when all elements are ",(0,r.jsx)(n.code,{children:"#f"}),", and return ",(0,r.jsx)(n.code,{children:"#t"})," immediately when any of the values is ",(0,r.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (or (< 1 2) (/ 1 0))\n (display "true"))\n;; ==> true\n'})}),"\n",(0,r.jsxs)(n.p,{children:["This expression will not evaluate ",(0,r.jsx)(n.code,{children:"(/ 1 0)"})," which will give ",(0,r.jsx)(n.strong,{children:"Division by zero"})," error because it\nstop evaluating when it finds the first true value."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"not"})," - not negates the value. If the value is true it will return ",(0,r.jsx)(n.code,{children:"#f"})," otherwise it will return ",(0,r.jsx)(n.code,{children:"#t"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (not (zero? 10))\n (display "not zero"))\n;; ==> not zero\n'})}),"\n",(0,r.jsx)(n.h2,{id:"procedures",children:"Procedures"}),"\n",(0,r.jsxs)(n.p,{children:["To define a procedure or a function, you use ",(0,r.jsx)(n.code,{children:"lambda"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define square (lambda (x) (* x x)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This defines a function square that multiply its argument by itself. Lambda is a way to create\nanonymous function and define assign it to the symbol square. The name ",(0,r.jsx)(n.code,{children:"lambda"})," is nowadays common\nname to define anonymous function (example in languages like python or Java), but the name came from\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Lambda_calculus",children:"Lambda Calculus"})]}),"\n",(0,r.jsx)(n.p,{children:"There is also a shortcut to define procedure/function:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (square (x) (* x x)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["There are no explicit ",(0,r.jsx)(n.code,{children:"return"})," statement. Only the last expression of the function is the result value."]}),"\n",(0,r.jsx)(n.p,{children:"You can also add more arguments:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b)\n (+ a b))\n(sum 10 20)\n;; ==> 30\n"})}),"\n",(0,r.jsx)(n.h3,{id:"nested-procedures",children:"Nested Procedures"}),"\n",(0,r.jsx)(n.p,{children:"You can define inner procedures inside other procedures:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (cube x)\n (define (square x)\n (* x x))\n (* x (square x)))\n"})}),"\n",(0,r.jsx)(n.h3,{id:"immediately-invoked-lambda",children:"Immediately invoked lambda"}),"\n",(0,r.jsx)(n.p,{children:"When calling a function, that first element doesn't need to be a symbol. It can be expression which\nevaluates to a function. So you can use lambda expression as first argument, but don't call it only\nevaluate it immediately, without saving it in a variable."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"((lambda (x) (* x x)) 10)\n;; ==> 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"variable-number-of-arguments",children:"Variable number of arguments"}),"\n",(0,r.jsxs)(n.p,{children:["Built-in ",(0,r.jsx)(n.code,{children:"+"})," function allow summing all its arguments. You can create function that accept variable\nnumber of arguments yourself."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define sum (lambda args (apply + args)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This function invokes a function ",(0,r.jsx)(n.code,{children:"+"})," with its arguments. Note that are no parentheses around\narguments. So all arguments will be saved inside ",(0,r.jsx)(n.code,{children:"args"})," parameter. ",(0,r.jsx)(n.code,{children:"apply"})," can be called with\nprocedure as first argument, multiple arguments and last argument needs to be a list."]}),"\n",(0,r.jsx)(n.p,{children:"if you invoke"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(sum 1 2 3 4)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"args"})," will contain a list ",(0,r.jsx)(n.code,{children:"'(1 2 3 4)"}),". The same, you can use improper list (with dot inside)\nas arguments:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define expression (lambda (first . rest) (/ first (apply + rest))))\n(expression 1 2 3 4)\n;; ==> 1/9\n"})}),"\n",(0,r.jsx)(n.h3,{id:"optional-arguments",children:"Optional arguments"}),"\n",(0,r.jsx)(n.p,{children:"When using improper lists as function parameter, you can create optional arguments:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (rational first . rest)\n (let ((second (if (null? rest) 1 (car rest))))\n (/ first second)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This will create a procedure that have second argument optional. When invoking:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(rational 10)\n"})}),"\n",(0,r.jsx)(n.p,{children:"it will evaluate:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(/ 10 1)\n;; ==> 10\n"})}),"\n",(0,r.jsx)(n.p,{children:"and when you evaluate:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(rational 1 2)\n;; ==> 1/2\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If scheme provides rational numbers, or it will return ",(0,r.jsx)(n.code,{children:"0.5"})," otherwise."]}),"\n",(0,r.jsx)(n.h3,{id:"recursion",children:"Recursion"}),"\n",(0,r.jsx)(n.p,{children:"You can define a function that reference to itself:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (if (<= n 1)\n 1\n (* n (factorial (- n 1)))))\n\n(factorial 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsxs)(n.p,{children:["There is a main if statement that is called base condition. If the value ",(0,r.jsx)(n.code,{children:"n"})," is less or equal 1 it\nstop recursion and return 1. If not, it calls itself recursively decreasing the value ",(0,r.jsx)(n.code,{children:"n"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You can also define recursion using named ",(0,r.jsx)(n.code,{children:"let"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (let loop ((n n))\n (if (<= n 1)\n 1\n (* n (loop (- n 1))))))\n\n(factorial 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsx)(n.h4,{id:"local-recursive-functions",children:"Local Recursive Functions"}),"\n",(0,r.jsxs)(n.p,{children:["By default, you can define a local variable with let that is a ",(0,r.jsx)(n.code,{children:"lambda"})," that reference itself. But you can do this with ",(0,r.jsx)(n.code,{children:"letrec"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(letrec ((sum (lambda (x)\n (if (zero? x)\n 0\n (+ x (sum (- x 1)))))))\n (sum 10))\n;; ==> 55\n"})}),"\n",(0,r.jsx)(n.h3,{id:"tail-call-optimization",children:"Tail Call Optimization"}),"\n",(0,r.jsxs)(n.p,{children:["When you create recursive function and with deeply nested calls, you may run out of memory. This type of\nerror is called ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Stack_buffer_overflow",children:"Stack Overflow"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Scheme have unique feature called TCO and optimize the code and don't consume the stack when\ncalculation, deeply recursive function. The code written in TCO will never lead to Stack Overflow errors."}),"\n",(0,r.jsx)(n.p,{children:"This is an example of Tail Call:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (let loop ((n n) (result 1))\n (if (<= n 1)\n result\n (loop (- n 1) (* n result)))))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This function is similar to previous recursive function, but note that loop is the last expression,\nthe result of loop don't need to wait on anything. This type of code is optimized by Scheme and can\nrecur any number of types."}),"\n",(0,r.jsx)(n.p,{children:"If you need to create a recursive procedure that accumulate something, like create a list of create\na value, you need to add additional variable where you will old that value, the local variable is\nofen called result, but you can name it like you want."}),"\n",(0,r.jsx)(n.h2,{id:"loops",children:"Loops"}),"\n",(0,r.jsxs)(n.p,{children:["Recursion is not the only way to create loops in Scheme. You also have ",(0,r.jsx)(n.code,{children:"do"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(do ((i 1 (+ i 1))\n (result '() (cons i result)))\n ((> i 10) result)\n (display i)\n (newline))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["First list of do expression have variable initialization and increment, there can be more\nexpressions. In the above example, we have ",(0,r.jsx)(n.code,{children:"i"})," and ",(0,r.jsx)(n.code,{children:"result"})," variables. The ",(0,r.jsx)(n.code,{children:"i"})," variable is incremented by\n1 starting from 1. And ",(0,r.jsx)(n.code,{children:"result"})," starts from empty list and add element to the list using ",(0,r.jsx)(n.code,{children:"cons"}),".\nThe second list have two values, stop condition and result of the whole expression. The rest is body\nthat is executed on each iteration."]}),"\n",(0,r.jsx)(n.p,{children:"So the code will print each number and return a list of numbers."}),"\n",(0,r.jsx)(n.h2,{id:"list-operations",children:"List operations"}),"\n",(0,r.jsxs)(n.p,{children:["You can use ",(0,r.jsx)(n.code,{children:"list-ref"})," to reference nth element of the list"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(1 2 3 4 5 6 7)))\n (print (cadddr lst))\n (print (list-ref lst 3)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Both expressions in let will print number ",(0,r.jsx)(n.code,{children:"4"})," which is the 4th element of the list."]}),"\n",(0,r.jsx)(n.h3,{id:"iterating-over-a-list-recursively",children:"Iterating over a list recursively"}),"\n",(0,r.jsx)(n.p,{children:"This is the basic pattern you use to iterate over a list using recursion:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (operation lst)\n (if (null? lst)\n ...\n (operation (cdr lst))))\n\n"})}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of a function that check if an element is present in the list:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (contains item lst)\n (if (null? lst)\n #f\n (if (equal? item (car lst))\n #t\n (contains item (cdr lst)))))\n\n\n(let ((lst '(1 2 3 4 5 6 0 7 8 9)))\n (print (contains 0 lst)))\n;; ==> #t\n\n(let ((lst '(1 2 3 4 5 6 0 7 8 9)))\n (print (contains \"x\" lst)))\n;; ==> #f\n"})}),"\n",(0,r.jsx)(n.h3,{id:"alists",children:"Alists"}),"\n",(0,r.jsx)(n.p,{children:"Alists (or Association list) is a way to create objects in Scheme using lists. The alist is created with\nlist of cons cells:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(list (cons "x" 10) (cons "y" 20) (cons "z" 30))\n;; ==> (("x" . 10) ("y" . 20) ("z" . 30))\n'})}),"\n",(0,r.jsx)(n.p,{children:"You can also create alist using quotation:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'\'(("x" . 10) ("y" . 20) ("z" . 30))\n'})}),"\n",(0,r.jsx)(n.p,{children:"You have 3 functions that operate on alists:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assq"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assoc"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The return pair that match first argument or ",(0,r.jsx)(n.code,{children:"#f"})," if not found. The alist is passed as second\nargument. They use ",(0,r.jsx)(n.code,{children:"eq?"}),", ",(0,r.jsx)(n.code,{children:"eqv?"}),", and ",(0,r.jsx)(n.code,{children:"equal?"})," respectively."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x '((foo . 10) (bar . 20) (baz . 30))))\n (print (assoc 'bar x))\n (print (assoc 'quux x)))\n;; ==> (bar . 20)\n;; ==> #f\n"})}),"\n",(0,r.jsxs)(n.p,{children:["First call will return pair ",(0,r.jsx)(n.code,{children:"(bar . 20)"})," because its ",(0,r.jsx)(n.code,{children:"bar"})," symbol is present in the alist. And the\nsecond call will print ",(0,r.jsx)(n.code,{children:"#f"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You can use ",(0,r.jsx)(n.code,{children:"cond"})," expression with ",(0,r.jsx)(n.code,{children:"=>"})," syntax to get the value of alist:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let* ((alist '((foo . 10) (bar . 20) (baz . 30)))\n (result (cond ((assoc 'bar alist) => cdr)\n (else '()))))\n (if result\n (print result)))\n;; ==> 20\n"})}),"\n",(0,r.jsx)(n.h2,{id:"finding-element-in-the-list",children:"Finding element in the list"}),"\n",(0,r.jsx)(n.p,{children:"Similar to operation on alist there are 3 functions that find if the element is present in the normal list"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"memq"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"memv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"member"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The return cons cell where ",(0,r.jsx)(n.code,{children:"car"})," match object passed as first argument or #f if not found:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(1 2 3 x y z)))\n (print (member 'x lst))\n (print (member 'foo lst)))\n;; ==> (x y z)\n;; ==> #f\n"})}),"\n",(0,r.jsx)(n.h2,{id:"vector-operations",children:"Vector operations"}),"\n",(0,r.jsx)(n.p,{children:"Same as operation on list you can operate on list, you have different procedure to operate on vectors."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((v (vector #\\h #\\e #\\l #\\l #\\o)))\n (write (vector-ref v 0))\n (newline)\n (vector-set! v 0 #\\H)\n (write (vector-ref v 0))\n (newline)\n (print (vector->string v))\n (newline))\n;; ==> #\\h\n;; ==> #\\H\n;; ==> Hello\n"})}),"\n",(0,r.jsxs)(n.p,{children:["To check if an option is a vector, you can use ",(0,r.jsx)(n.code,{children:"vector?"})," predicate."]}),"\n",(0,r.jsx)(n.h2,{id:"string-operations",children:"String operations"}),"\n",(0,r.jsx)(n.p,{children:"Similar to operation on vectors and lists, you have procedures to operate on strings."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(let ((str (string #\\h #\\e #\\l #\\l #\\o)))\n (write (string-ref str 0))\n (newline)\n (string-set! str 0 #\\H)\n (write (string-ref str 0))\n (newline)\n (write str)\n (newline))\n;; ==> #\\h\n;; ==> #\\H\n;; ==> "Hello"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To check if an object is a string, you can use ",(0,r.jsx)(n.code,{children:"string?"})," predicate."]}),"\n",(0,r.jsx)(n.h2,{id:"multiple-values",children:"Multiple values"}),"\n",(0,r.jsxs)(n.p,{children:["By default, functions in Scheme return a single value, but you can return multiple values with ",(0,r.jsx)(n.code,{children:"values"})," expression."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (div-mul x y)\n (values (/ x y) (* x y)))\n\n(define (plus-minus x y)\n (values (+ x y) (- x y)))\n\n(display (div-mul 2 10))\n;; ==> 1/5 20\n(display (plus-minus 2 10))\n;; ==> 12 -8\n"})}),"\n",(0,r.jsx)(n.p,{children:"When you try to use this value in expression:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x (div-mul 2 10)))\n (display (* x 2)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"Some Scheme implementation will evaluate that expression and get the first value. And some\nimplementation will throw an error about expecting number but got multiple values."}),"\n",(0,r.jsxs)(n.p,{children:["To safety access both values, you can use ",(0,r.jsx)(n.code,{children:"call-with-values"})," procedure:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(call-with-values (lambda () (div-mul 2 10))\n (lambda (div mul)\n (display div)\n (newline)\n (display mul)\n (newline)))\n;; ==> 1/5\n;; ==> 20\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You also have ",(0,r.jsx)(n.code,{children:"let-values"})," and ",(0,r.jsx)(n.code,{children:"let*-values"})," expressions, that works similar to ",(0,r.jsx)(n.code,{children:"let"})," and ",(0,r.jsx)(n.code,{children:"let*"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let-values (((plus minus) (plus-minus 2 10))\n ((div mul) (div-mul 2 10)))\n (+ div mul plus minus))\n;; ==> 121/5\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that there are two open parentheses before div. The pair is like with let:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x (div-mul 2 10)))\n ...)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["And instead of ",(0,r.jsx)(n.code,{children:"x"})," you have a list with two values that came from ",(0,r.jsx)(n.code,{children:"values"})," expression."]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"let-values"})," also accept normal (single value expression like ",(0,r.jsx)(n.code,{children:"let"}),") so you can mix them.\nSingle expression still need to be a list but with a single value."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let*-values (((x) 2)\n ((y) 10)\n ((div mul) (div-mul x y)))\n (+ div mul))\n;; ==> 101/5\n"})}),"\n",(0,r.jsx)(n.h2,{id:"higher-order-functions",children:"Higher order functions"}),"\n",(0,r.jsxs)(n.p,{children:["Functions in Scheme are ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/First-class_citizen",children:"first class"}),", which\nmeans that are the same as any other values like numbers. And can be passed around. You can create a\nfunction that accept other function or create a function that return a function. Functions that\noperate on functions are called ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Higher-order_function",children:"higher order\nfunctions"})," or higher order procedures."]}),"\n",(0,r.jsxs)(n.p,{children:["Scheme define few built in higher order functions like ",(0,r.jsx)(n.code,{children:"map"}),", ",(0,r.jsx)(n.code,{children:"for-each"})," they both accept a function\nand execute them for every element of the list. ",(0,r.jsx)(n.code,{children:"map"})," return new list from the values and ",(0,r.jsx)(n.code,{children:"for-each"}),"\nreturn unspecified value."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(map square '(1 2 3 4))\n;; ==> (1 4 9 16)\n(map (lambda (x) (* x 10)) '(1 2 3 4))\n;; ==> (10 20 30 40)\n"})}),"\n",(0,r.jsx)(n.p,{children:"You can also define your own higher order functions:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (filter fn lst)\n (if (null? lst)\n '()\n (let ((item (car lst)))\n (if (fn item)\n (cons item (filter fn (cdr lst)))\n (filter fn (cdr lst))))))\n\n(filter odd? '(1 2 3 4 5))\n;; ==> (1 3 5)\n(filter (lambda (x) (not (zero? x))) '(1 2 0 3 0 0 0 4 5 0 6 7))\n;; ==> (1 2 3 4 5 6 7)\n"})}),"\n",(0,r.jsx)(n.p,{children:"You can use function that return lambda to create different list accessors for elements more than 4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (list-selector n)\n (lambda (list)\n (list-ref list n)))\n\n(define first car)\n(define rest cdr)\n(define second cadr)\n(define third caddr)\n(define fourth cadddr)\n(define fifth (list-selector 4))\n(define sixth (list-selector 5))\n(define seventh (list-selector 6))\n(define eighth (list-selector 7))\n(define ninth (list-selector 8))\n(define tenth (list-selector 9))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Another useful procedure is ",(0,r.jsx)(n.code,{children:"alist-map"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (alist-map fun alist)\n (map (lambda (item) (fun (car item) (cdr item))) alist))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You can use this procedure to map over values or keys inside an ",(0,r.jsx)(n.a,{href:"#alists",children:"alist"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define alist (map cons '(a b c d) '(1 2 3 4)))\n\n(alist-map (lambda (key value) (cons key (* value 10))) alist)\n;; ==> ((a . 10) (b . 20) (c . 30) (d . 40))\n(define (symbol-upcase symbol)\n (string->symbol (string-upcase (symbol->string symbol))))\n\n(alist-map (lambda (key value) (cons (symbol-upcase key) value)) alist)\n;; ==> ((A . 1) (B . 2) (C . 3) (D . 4))\n"})}),"\n",(0,r.jsx)(n.h2,{id:"closures",children:"Closures"}),"\n",(0,r.jsx)(n.p,{children:"Scheme have lexical scope. Which means that if functions don't define a variable Scheme search them\noutside in the place where procedure was defined. This allows to create closures. Which are basically\nfunctions that have access to variables defined outside. Scheme need to keep environment in where\nprocedure was defined together with a procedure."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define counter (let ((count 0))\n (lambda ()\n (set! count (+ count 1))\n count)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This creates a function that have access to a variable defined outside in let expression."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(counter)\n;; ==> 1\n(counter)\n;; ==> 2\n(counter)\n;; ==> 3\n"})}),"\n",(0,r.jsx)(n.p,{children:"With this, you can create functions that create counters that start with a given number:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (make-counter n)\n (let ((count n))\n (lambda ()\n (set! count (+ count 1))\n count)))\n\n(define counter-1 (make-counter 100))\n(define counter-2 (make-counter 0))\n\n(counter-1)\n;; ==> 101\n(counter-1)\n;; ==> 102\n(counter-2)\n;; ==> 1\n(counter-1)\n;; ==> 103\n(counter-2)\n;; ==> 2\n"})}),"\n",(0,r.jsx)(n.p,{children:"Each counter has its own local state and its own counter variable."}),"\n",(0,r.jsx)(n.h2,{id:"objects",children:"Objects"}),"\n",(0,r.jsx)(n.p,{children:"In Scheme you can have objects (data with behavior), the base code for objects use closures."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(define (make-person name age)\n (lambda (action . rest)\n (case action\n ((name) name)\n ((age) age)\n ((set-name) (set! name (car rest)))\n ((set-age) (set! age (car rest))))))\n\n(let ((jack (make-person "Jack" 22)))\n (display (jack \'name))\n (newline)\n (jack \'set-name "Mark")\n (jack \'set-age 24)\n (display (jack \'name))\n (display " is ")\n (display (jack \'age))\n (display " years old"))\n;; ==> Jack\n;; ==> Mark is 24 years old\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Notice that it's function which returns a function (",(0,r.jsx)(n.code,{children:"lambda"}),"). You can send a message into that object,\nit will process it by returning a value from closure or mutating that value."]}),"\n",(0,r.jsxs)(n.p,{children:["In the same way you can use ",(0,r.jsx)(n.a,{href:"#alists",children:"alist"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"records",children:"Records"}),"\n",(0,r.jsxs)(n.p,{children:["Anther way to create objects in Scheme, are R",(0,r.jsx)("sup",{children:"7"}),"RS records, they were first defined in\n",(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-9",children:"SRFI-9"})," and included in the official standard."]}),"\n",(0,r.jsx)(n.p,{children:"You can define records that represent cons cells to create linked lists:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define-record-type :pare\n (kons x y)\n pare?\n (x kar set-kar!)\n (y kdr))\n"})}),"\n",(0,r.jsx)(n.p,{children:"The record type is defined with:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"constructor"}),"\n",(0,r.jsx)(n.li,{children:"predicate that test if the element is of given type"}),"\n",(0,r.jsx)(n.li,{children:"and list of fields"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"You can use this record like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(define k (kons 1 2))\n(pare? k)\n;; ==> #t\n(kar k)\n;; ==> 1\n(kdr k)\n;; ==> 2\n(set-kar! k 2)\n(cons (kar k) (kdr k))\n;; ==> (2 . 2)\n\n(define (klist . args)\n (if (null? args)\n ()\n (kons (car args) (apply klist (cdr args)))))\n\n(define (kprint klist)\n (display "(")\n (let loop ((klist klist))\n (when (not (null? klist))\n (display (kar klist))\n (let ((rest (kdr klist)))\n (unless (null? rest)\n (display " ")\n (loop rest)))))\n (display ")"))\n\n(define kl (klist 1 2 3 4))\n\n(kar (kdr (kdr (kdr kl))))\n;; ==> 4\n\n(kprint kl)\n;; ==> (1 2 3 4)\n'})}),"\n",(0,r.jsx)(n.h2,{id:"dynamic-variables",children:"Dynamic variables"}),"\n",(0,r.jsxs)(n.p,{children:["Even that Scheme has lexical scope, you can define dynamic variables. They are the opposite of\nlexical variables. When you define a dynamic variable, Scheme will search for them not in the place\nwhere function is defined, but in the place where it's called. That's why if you have fully dynamic lisp\nyou can't have closures. Unless you can somehow add lexical variables. This is the case of\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Emacs_Lisp",children:"Emacs Lisp"}),", lisp that is embedded into an\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Emacs",children:"Emacs editor"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"To create dynamic variable in Scheme, you can code like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define x (make-parameter 0))\n\n(define (add-x y)\n (+ (x) y))\n\n(add-x 10)\n;; ==> 10\n(parameterize ((x 10))\n (add-x 10))\n;; ==> 20\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Parameters works like procedures. Do define new dynamic parameter you use ",(0,r.jsx)(n.code,{children:"make-parameter"})," and to\nchange its value you can use ",(0,r.jsx)(n.code,{children:"parameterize"})," that works like ",(0,r.jsx)(n.code,{children:"let"}),". You can also call the parameter\nwith different value and the parameter will use this value as default."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(x 10)\n(add-x 10)\n;; ==> 20\n(parameterize ((x 3))\n (add-x 3))\n;; ==> 6\n"})}),"\n",(0,r.jsx)(n.h2,{id:"loading-of-external-code",children:"Loading of external code"}),"\n",(0,r.jsxs)(n.p,{children:["You can execute external code inside Scheme by using ",(0,r.jsx)(n.code,{children:"load"})," procedure."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(load "file.scm")\n'})}),"\n",(0,r.jsxs)(n.p,{children:["This will load an external file named ",(0,r.jsx)(n.code,{children:"file.scm"}),". Scheme files often end with ",(0,r.jsx)(n.code,{children:"scm"}),", but different\nscheme implementation may use different convention."]}),"\n",(0,r.jsx)(n.h2,{id:"eval",children:"Eval"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"eval"})," procedure is used to evaluate code that is written as data."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define expr '(+ 1 2))\n(eval expr)\n;; ==> 3\n"})}),"\n",(0,r.jsx)(n.p,{children:"Some scheme implementation may require to specify second argument which is environment."}),"\n",(0,r.jsx)(n.p,{children:"You can use those procedures to get different environments:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"(interaction-environment)"})," - this return environment for the REPL"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"(scheme-report-environment )"})," - creates environment with functions from a given\nR",(0,r.jsx)("sup",{children:"n"}),"RS specification"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"scheme-libraries",children:"Scheme libraries"}),"\n",(0,r.jsxs)(n.p,{children:["R",(0,r.jsx)("sup",{children:"7"}),"RS standard of Scheme also define a way to define libraries. This is a common way to\ncreate modules that can be used inside your project or my other people."]}),"\n",(0,r.jsxs)(n.p,{children:["To import a library that is part of the scheme implementation, you use ",(0,r.jsx)(n.code,{children:"import"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(import (srfi 1))\n\n(zip '(1 2 3)\n '(foo bar baz)\n '(one two three))\n;; ==> ((1 foo one) (2 bar two) (3 baz three))\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-1/srfi-1.html",children:"SRFI-1"})," is SRFI that defines a library of procedures\nthat operate on lists (like ",(0,r.jsx)(n.code,{children:"zip"})," procedure that join multiple lists)."]}),"\n",(0,r.jsxs)(n.p,{children:["You can define your own libraries with ",(0,r.jsx)(n.code,{children:"define-library"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define-library (example factorial)\n (export !)\n (import (scheme base))\n (begin\n (define (range n)\n (let loop ((n n) (result '()))\n (if (<= n 0)\n result\n (loop (- n 1) (cons n result)))))\n (define (! n)\n (apply * (range n)))))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This is definition of library ",(0,r.jsx)(n.code,{children:"(example factorial)"})," that define single procedure ",(0,r.jsx)(n.code,{children:"!"})," that calculate\nfactorial of a number. It defines helper hidden (not exported) procedure ",(0,r.jsx)(n.code,{children:"range"})," that creates a list\nof numbers from ",(0,r.jsx)(n.code,{children:"1"})," to ",(0,r.jsx)(n.code,{children:"n"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"You can use this library like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(import (example factorial))\n(! 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsx)(n.h2,{id:"portable-code",children:"Portable code"}),"\n",(0,r.jsxs)(n.p,{children:["Scheme implementation differ. And it's hard to write code that will work on multiple Scheme\nInterpreters. Luckily in ",(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-0/srfi-0.html",children:"SRFI-0"})," (first SRFI ever\ncreated). There is defined special syntax called ",(0,r.jsx)(n.code,{children:"cond-expand"}),". A lot of Scheme implementations have\nthis SRFI built-in so you can use it to detect different Scheme and create code that will match that\nImplementation."]}),"\n",(0,r.jsx)(n.p,{children:"You can use it like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(cond-expand\n (kawa)\n (guile)\n (lips)\n (gauche)\n (else))\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"cond-expand"})," have list of lists in format ",(0,r.jsx)(n.code,{children:"(identifier . code)"}),". For example, if you want to add\n",(0,r.jsx)(n.code,{children:"print"})," function that is defined in ",(0,r.jsx)(n.code,{children:"LIPS"}),", but not in other implementations, you can use code like\nthis:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(cond-expand\n (lips)\n (else\n (define (print . args)\n (for-each (lambda (arg)\n (display arg)\n (newline))\n args))\n (define (lips.parse expr)\n (with-input-from-port (open-input-string expr)\n (lambda ()\n (do ((result '() (cons (read) result)))\n ((eof-object? (peek-char)) (list->vector (reverse result)))))))))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["It will evaluate an empty list for ",(0,r.jsx)(n.code,{children:"LIPS"})," and ",(0,r.jsx)(n.code,{children:"define"})," a new ",(0,r.jsx)(n.code,{children:"print"})," and ",(0,r.jsx)(n.code,{children:"lips.parse"})," procedures for\nother implementations. Those procedures are part of LIPS Scheme, see ",(0,r.jsx)(n.a,{href:"/docs/lips/intro",children:"LIPS\nTutorial"}),". Some Scheme implementations may not support ",(0,r.jsx)(n.code,{children:"with-input-from-port"}),"\n(like GNU Kawa) so it may require to add implementation for it."]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>c});var i=s(6540);const r={},l=i.createContext(r);function a(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/413466e5.6d557cee.js b/assets/js/413466e5.6d557cee.js deleted file mode 100644 index 9d485eda..00000000 --- a/assets/js/413466e5.6d557cee.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[8649],{1977:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>t,contentTitle:()=>c,default:()=>h,frontMatter:()=>a,metadata:()=>i,toc:()=>d});const i=JSON.parse('{"id":"scheme-intro/core","title":"Core of Scheme","description":"Main article that shows most of the features of Scheme","source":"@site/docs/scheme-intro/core.md","sourceDirName":"scheme-intro","slug":"/scheme-intro/core","permalink":"/docs/scheme-intro/core","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/scheme-intro/core.md","tags":[],"version":"current","sidebarPosition":3,"frontMatter":{"sidebar_position":3,"description":"Main article that shows most of the features of Scheme"},"sidebar":"tutorialSidebar","previous":{"title":"Data Types","permalink":"/docs/scheme-intro/data-types"},"next":{"title":"Input and Output","permalink":"/docs/scheme-intro/input-output"}}');var r=s(4848),l=s(8453);const a={sidebar_position:3,description:"Main article that shows most of the features of Scheme"},c="Core of Scheme",t={},d=[{value:"Printing values",id:"printing-values",level:2},{value:"Math expressions",id:"math-expressions",level:2},{value:"Boolean expression",id:"boolean-expression",level:3},{value:"Functions that returns part of the number",id:"functions-that-returns-part-of-the-number",level:3},{value:"Predicates",id:"predicates",level:2},{value:"Equal operation",id:"equal-operation",level:3},{value:"String and character comparators",id:"string-and-character-comparators",level:3},{value:"Symbols",id:"symbols",level:3},{value:"Type Predicates",id:"type-predicates",level:3},{value:"Variables",id:"variables",level:2},{value:"Modification of the variable",id:"modification-of-the-variable",level:3},{value:"Local variables",id:"local-variables",level:2},{value:"Conditionals",id:"conditionals",level:2},{value:"Boolean expressions",id:"boolean-expressions",level:2},{value:"Procedures",id:"procedures",level:2},{value:"Nested Procedures",id:"nested-procedures",level:3},{value:"Immediately invoked lambda",id:"immediately-invoked-lambda",level:3},{value:"Variable number of arguments",id:"variable-number-of-arguments",level:3},{value:"Optional arguments",id:"optional-arguments",level:3},{value:"Recursion",id:"recursion",level:3},{value:"Local Recursive Functions",id:"local-recursive-functions",level:4},{value:"Tail Call Optimization",id:"tail-call-optimization",level:3},{value:"Loops",id:"loops",level:2},{value:"List operations",id:"list-operations",level:2},{value:"Iterating over a list recursively",id:"iterating-over-a-list-recursively",level:3},{value:"Alists",id:"alists",level:3},{value:"Finding element in the list",id:"finding-element-in-the-list",level:2},{value:"Vector operations",id:"vector-operations",level:2},{value:"String operations",id:"string-operations",level:2},{value:"Multiple values",id:"multiple-values",level:2},{value:"Higher order functions",id:"higher-order-functions",level:2},{value:"Closures",id:"closures",level:2},{value:"Objects",id:"objects",level:2},{value:"Records",id:"records",level:3},{value:"Dynamic variables",id:"dynamic-variables",level:2},{value:"Loading of external code",id:"loading-of-external-code",level:2},{value:"Eval",id:"eval",level:2},{value:"Scheme libraries",id:"scheme-libraries",level:2},{value:"Portable code",id:"portable-code",level:2}];function o(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"core-of-scheme",children:"Core of Scheme"})}),"\n",(0,r.jsx)(n.h2,{id:"printing-values",children:"Printing values"}),"\n",(0,r.jsx)(n.p,{children:"To print a value, you can use two type of expressions:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(display "hello")\n;; ==> hello\n'})}),"\n",(0,r.jsx)(n.p,{children:"and"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(write "hello")\n;; ==> "hello"\n'})}),"\n",(0,r.jsx)(n.p,{children:"The first will print text hello without quotations. But the second will include the quotes. The\nsecond expression allows saving the expression and later read it as Scheme code."}),"\n",(0,r.jsx)(n.p,{children:"Both expression don't add newline at the end. To add a newline, you need to use:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(newline)\n"})}),"\n",(0,r.jsx)(n.p,{children:"Or you can use escape newline character:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(display "\\n")\n'})}),"\n",(0,r.jsx)(n.h2,{id:"math-expressions",children:"Math expressions"}),"\n",(0,r.jsx)(n.p,{children:"Scheme defines standard Math operations:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"+"})," - sum all its arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"-"})," - subtract the arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"/"})," - divide the arguments"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"*"})," - multiply the arguments"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"All the above can accept zero or more arguments."}),"\n",(0,r.jsx)(n.p,{children:"Trigonometry functions:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"sin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"cos"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"tan"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"asin"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"acos"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"atan"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"logarithms:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"log"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Exponentiation function:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"expt"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"Exponential function"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"exp"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"It also defines:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"square"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"sqrt"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"boolean-expression",children:"Boolean expression"}),"\n",(0,r.jsxs)(n.p,{children:["Expressions that returns ",(0,r.jsx)(n.code,{children:"true"})," or ",(0,r.jsx)(n.code,{children:"false"})," and operate on numbers"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"<"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:">"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"<="})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:">="})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"="})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"functions-that-returns-part-of-the-number",children:"Functions that returns part of the number"}),"\n",(0,r.jsx)(n.p,{children:"Rational and complex numbers are created from two different numbers."}),"\n",(0,r.jsx)(n.p,{children:"Rational numbers are created from numerator and denominator, and you can get those numbers from a single rational:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(numerator 1/2)\n;; ==> 1\n(denominator 1/2)\n;; ==> 2\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"NOTE:"})," The result values of those expressions are written as comments."]}),"\n",(0,r.jsx)(n.p,{children:"Complex numbers are created with real and imaginary parts, and you can also extract those parts:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(imag-part 10+2i)\n;; ==> 2\n(real-part 10+2i)\n;; ==> 10\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Scheme also define two functions ",(0,r.jsx)(n.code,{children:"angle"})," and ",(0,r.jsx)(n.code,{children:"magnitude"})," which can be used to get modulus and argument."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(angle 10+10i)\n;; ==> 0.7853981633974483\n(magnitude 10+10i)\n;; ==> 14.142135623730951\n"})}),"\n",(0,r.jsx)(n.h2,{id:"predicates",children:"Predicates"}),"\n",(0,r.jsx)(n.h3,{id:"equal-operation",children:"Equal operation"}),"\n",(0,r.jsx)(n.p,{children:"In Scheme there are a different way to compare values:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"eq?"})," - compares if the values are the same object works only on basic types"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"eqv?"})," - compares if the values have the same representation"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"equal?"})," - also works any type of values, it can compare vectors and list if they are the same"]}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"string-and-character-comparators",children:"String and character comparators"}),"\n",(0,r.jsx)(n.p,{children:"In addition, there are also comparators for strings:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"characters:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"String and characters also have counterpart procedures for compare with case-insensitive way:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string-ci>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"characters:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci<=?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char-ci>=?"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"symbols",children:"Symbols"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"symbol=?"})}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"type-predicates",children:"Type Predicates"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"pair?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"list?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"null?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"symbol?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"boolean?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"number?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"string?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"char?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"integer?"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"complex?"})}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"variables",children:"Variables"}),"\n",(0,r.jsxs)(n.p,{children:["To define a variable in Scheme you use ",(0,r.jsx)(n.code,{children:"define"})," special form:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define number 10)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This will define variable ",(0,r.jsx)(n.code,{children:"number"})," with value 10. You can evaluate this variable and get the value back."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"number\n"})}),"\n",(0,r.jsx)(n.p,{children:"This will evaluate to 10. Note that this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"'number\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Will evaluate into symbol ",(0,r.jsx)(n.code,{children:"number"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"modification-of-the-variable",children:"Modification of the variable"}),"\n",(0,r.jsxs)(n.p,{children:["To modify (mutate) existing variable, you use ",(0,r.jsx)(n.code,{children:"set!"})," procedure. There is a conversion of using exclamation\nmark for destructive type of procedure. Which are procedures that modify its arguments."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define number 10)\n(set! number (+ number 1))\n(display number)\n;; ==> 11\n"})}),"\n",(0,r.jsxs)(n.p,{children:["In the above expression, the number is increased by ",(0,r.jsx)(n.code,{children:"1"}),". The number in ",(0,r.jsx)(n.code,{children:"(+ number 1)"})," reference old value\nof the variable. And ",(0,r.jsx)(n.code,{children:"set!"})," special form update the variable with new value."]}),"\n",(0,r.jsx)(n.h2,{id:"local-variables",children:"Local variables"}),"\n",(0,r.jsxs)(n.p,{children:["You can create local variables with ",(0,r.jsx)(n.code,{children:"let"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x 10) (y 20))\n (+ x y))\n;; ==> 30\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This will create two variables ",(0,r.jsx)(n.code,{children:"x"})," and ",(0,r.jsx)(n.code,{children:"y"})," with values ",(0,r.jsx)(n.code,{children:"10"})," and ",(0,r.jsx)(n.code,{children:"20"})," respectively and sum those with\nplus procedure."]}),"\n",(0,r.jsxs)(n.p,{children:["There is also additional ",(0,r.jsx)(n.code,{children:"let*"})," expression that allow to return previous value in next expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let* ((x 10) (y (* x x)))\n (+ x y))\n;; ==> 110\n"})}),"\n",(0,r.jsxs)(n.p,{children:["And ",(0,r.jsx)(n.code,{children:"letrec"})," that allows to create local recursive functions (allow reference same binding):"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(letrec ((sum (lambda (list)\n (if (null? list)\n 0\n (+ (car list) (sum (cdr list)))))))\n (sum '(1 2 3 4)))\n;; ==> 10\n"})}),"\n",(0,r.jsx)(n.h2,{id:"conditionals",children:"Conditionals"}),"\n",(0,r.jsxs)(n.p,{children:["In Scheme there are 3 ways to define conditionals. The basic expression is ",(0,r.jsx)(n.code,{children:"if"})," statement."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (< 1 2)\n (write "this is true")\n (write "this is false"))\n'})}),"\n",(0,r.jsx)(n.p,{children:"If you need to put more than one expression inside if statement (or any other expression that\nexpect single expression) you can use begin:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (< 1 2)\n (begin\n (write "this is true")\n (newline)))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsx)(n.p,{children:"The else part is optional."}),"\n",(0,r.jsxs)(n.p,{children:["You also have a shortcut for this case in ",(0,r.jsx)(n.code,{children:"when"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(when (< 1 2)\n (write "this is true")\n (newline))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["There is also create the opposite with ",(0,r.jsx)(n.code,{children:"unless"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(unless #f\n (write "this is true")\n (newline))\n;; ==> "this is true"\n'})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"cond"})," is another expression that allow to add multiple conditions:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(cond ((< 2 2) (write "first"))\n ((< 2 1) (write "second"))\n (else\n (write "other")))\n;; ==> "other"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["The first two expressions return false, so ",(0,r.jsx)(n.code,{children:"cond"})," will evaluate the ",(0,r.jsx)(n.code,{children:"else"})," condition and display ",(0,r.jsx)(n.code,{children:'"other"'}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Case is the last of basic condition expressions. It allows checking given expression is one of the given values."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(let ((x \'foo))\n (case x\n ((one two) (display "first"))\n ((foo bar) (display "second"))\n (else\n (display "other"))))\n;; ==> second\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Symbol foo is of the second list, so this expression will print ",(0,r.jsx)(n.code,{children:'"second"'}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"boolean-expressions",children:"Boolean expressions"}),"\n",(0,r.jsx)(n.p,{children:"Scheme provide 3 boolean special forms that can be used to combine other expressions:"}),"\n",(0,r.jsxs)(n.p,{children:["They are not functions but special forms that can be used to create ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Short-circuit_evaluation",children:"Short-circuit\nevaluation"})," also called McCarthy evaluation\nfrom ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/John_McCarthy_(computer_scientist)",children:"John McCarthy"})," inventor of\nLisp."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"and"})," - returns ",(0,r.jsx)(n.code,{children:"true"})," when all elements are true value (in Scheme all values are true except ",(0,r.jsx)(n.code,{children:"#f"}),"),\nand stop evaluates when it finds ",(0,r.jsx)(n.code,{children:"#f"})]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (and (< 1 2) (> 3 1))\n (display "true"))\n;; ==> true\n'})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"or"})," - returns ",(0,r.jsx)(n.code,{children:"#f"})," when all elements are ",(0,r.jsx)(n.code,{children:"#f"}),", and return ",(0,r.jsx)(n.code,{children:"#t"})," immediately when any of the values is ",(0,r.jsx)(n.code,{children:"true"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (or (< 1 2) (/ 1 0))\n (display "true"))\n;; ==> true\n'})}),"\n",(0,r.jsxs)(n.p,{children:["This expression will not evaluate ",(0,r.jsx)(n.code,{children:"(/ 1 0)"})," which will give ",(0,r.jsx)(n.strong,{children:"Division by zero"})," error because it\nstop evaluating when it finds the first true value."]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"not"})," - not negates the value. If the value is true it will return ",(0,r.jsx)(n.code,{children:"#f"})," otherwise it will return ",(0,r.jsx)(n.code,{children:"#t"}),"."]}),"\n"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(if (not (zero? 10))\n (display "not zero"))\n;; ==> not zero\n'})}),"\n",(0,r.jsx)(n.h2,{id:"procedures",children:"Procedures"}),"\n",(0,r.jsxs)(n.p,{children:["To define a procedure or a function, you use ",(0,r.jsx)(n.code,{children:"lambda"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define square (lambda (x) (* x x)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This defines a function square that multiply its argument by itself. Lambda is a way to create\nanonymous function and define assign it to the symbol square. The name ",(0,r.jsx)(n.code,{children:"lambda"})," is nowadays common\nname to define anonymous function (example in languages like python or Java), but the name came from\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Lambda_calculus",children:"Lambda Calculus"})]}),"\n",(0,r.jsx)(n.p,{children:"There is also a shortcut to define procedure/function:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (square (x) (* x x)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["There are no explicit ",(0,r.jsx)(n.code,{children:"return"})," statement. Only the last expression of the function is the result value."]}),"\n",(0,r.jsx)(n.p,{children:"You can also add more arguments:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b)\n (+ a b))\n(sum 10 20)\n;; ==> 30\n"})}),"\n",(0,r.jsx)(n.h3,{id:"nested-procedures",children:"Nested Procedures"}),"\n",(0,r.jsx)(n.p,{children:"You can define inner procedures inside other procedures:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (cube x)\n (define (square x)\n (* x x))\n (* x (square x)))\n"})}),"\n",(0,r.jsx)(n.h3,{id:"immediately-invoked-lambda",children:"Immediately invoked lambda"}),"\n",(0,r.jsx)(n.p,{children:"When calling a function, that first element doesn't need to be a symbol. It can be expression which\nevaluates to a function. So you can use lambda expression as first argument, but don't call it only\nevaluate it immediately, without saving it in a variable."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"((lambda (x) (* x x)) 10)\n;; ==> 100\n"})}),"\n",(0,r.jsx)(n.h3,{id:"variable-number-of-arguments",children:"Variable number of arguments"}),"\n",(0,r.jsxs)(n.p,{children:["Built-in ",(0,r.jsx)(n.code,{children:"+"})," function allow summing all its arguments. You can create function that accept variable\nnumber of arguments yourself."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define sum (lambda args (apply + args)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This function invokes a function ",(0,r.jsx)(n.code,{children:"+"})," with its arguments. Note that are no parentheses around\narguments. So all arguments will be saved inside ",(0,r.jsx)(n.code,{children:"args"})," parameter. ",(0,r.jsx)(n.code,{children:"apply"})," can be called with\nprocedure as first argument, multiple arguments and last argument needs to be a list."]}),"\n",(0,r.jsx)(n.p,{children:"if you invoke"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(sum 1 2 3 4)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"args"})," will contain a list ",(0,r.jsx)(n.code,{children:"'(1 2 3 4)"}),". The same, you can use improper list (with dot inside)\nas arguments:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define expression (lambda (first . rest) (/ first (apply + rest))))\n(expression 1 2 3 4)\n;; ==> 1/9\n"})}),"\n",(0,r.jsx)(n.h3,{id:"optional-arguments",children:"Optional arguments"}),"\n",(0,r.jsx)(n.p,{children:"When using improper lists as function parameter, you can create optional arguments:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (rational first . rest)\n (let ((second (if (null? rest) 1 (car rest))))\n (/ first second)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This will create a procedure that have second argument optional. When invoking:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(rational 10)\n"})}),"\n",(0,r.jsx)(n.p,{children:"it will evaluate:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(/ 10 1)\n;; ==> 10\n"})}),"\n",(0,r.jsx)(n.p,{children:"and when you evaluate:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(rational 1 2)\n;; ==> 1/2\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If scheme provide rational numbers, or it will return ",(0,r.jsx)(n.code,{children:"0.5"})," otherwise."]}),"\n",(0,r.jsx)(n.h3,{id:"recursion",children:"Recursion"}),"\n",(0,r.jsx)(n.p,{children:"You can define a function that reference to itself:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (if (<= n 1)\n 1\n (* n (factorial (- n 1)))))\n\n(factorial 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsxs)(n.p,{children:["There is a main if statement that is called base condition. If the value ",(0,r.jsx)(n.code,{children:"n"})," is less or equal 1 it\nstop recursion and return 1. If not, it calls itself recursively decreasing the value ",(0,r.jsx)(n.code,{children:"n"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You can also define recursion using named ",(0,r.jsx)(n.code,{children:"let"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (let loop ((n n))\n (if (<= n 1)\n 1\n (* n (loop (- n 1))))))\n\n(factorial 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsx)(n.h4,{id:"local-recursive-functions",children:"Local Recursive Functions"}),"\n",(0,r.jsxs)(n.p,{children:["By default, you can define a local variable with let that is a ",(0,r.jsx)(n.code,{children:"lambda"})," that reference itself. But you can do this with ",(0,r.jsx)(n.code,{children:"letrec"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(letrec ((sum (lambda (x)\n (if (zero? x)\n 0\n (+ x (sum (- x 1)))))))\n (sum 10))\n;; ==> 55\n"})}),"\n",(0,r.jsx)(n.h3,{id:"tail-call-optimization",children:"Tail Call Optimization"}),"\n",(0,r.jsxs)(n.p,{children:["When you create recursive function and with deeply nested calls, you may run out of memory. This type of\nerror is called ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Stack_buffer_overflow",children:"Stack Overflow"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"Scheme have unique feature called TCO and optimize the code and don't consume the stack when\ncalculation, deeply recursive function. The code written in TCO will never lead to Stack Overflow errors."}),"\n",(0,r.jsx)(n.p,{children:"This is an example of Tail Call:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (factorial n)\n (let loop ((n n) (result 1))\n (if (<= n 1)\n result\n (loop (- n 1) (* n result)))))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This function is similar to previous recursive function, but note that loop is the last expression,\nthe result of loop don't need to wait on anything. This type of code is optimized by Scheme and can\nrecur any number of types."}),"\n",(0,r.jsx)(n.p,{children:"If you need to create a recursive procedure that accumulate something, like create a list of create\na value, you need to add additional variable where you will old that value, the local variable is\nofen called result, but you can name it like you want."}),"\n",(0,r.jsx)(n.h2,{id:"loops",children:"Loops"}),"\n",(0,r.jsxs)(n.p,{children:["Recursion is not the only way to create loops in Scheme. You also have ",(0,r.jsx)(n.code,{children:"do"})," syntax:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(do ((i 1 (+ i 1))\n (result '() (cons i result)))\n ((> i 10) result)\n (display i)\n (newline))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["First list of do expression have variable initialization and increment, there can be more\nexpressions. In the above example, we have ",(0,r.jsx)(n.code,{children:"i"})," and ",(0,r.jsx)(n.code,{children:"result"})," variables. The ",(0,r.jsx)(n.code,{children:"i"})," variable is incremented by\n1 starting from 1. And ",(0,r.jsx)(n.code,{children:"result"})," starts from empty list and add element to the list using ",(0,r.jsx)(n.code,{children:"cons"}),".\nThe second list have two values, stop condition and result of the whole expression. The rest is body\nthat is executed on each iteration."]}),"\n",(0,r.jsx)(n.p,{children:"So the code will print each number and return a list of numbers."}),"\n",(0,r.jsx)(n.h2,{id:"list-operations",children:"List operations"}),"\n",(0,r.jsxs)(n.p,{children:["You can use ",(0,r.jsx)(n.code,{children:"list-ref"})," to reference nth element of the list"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(1 2 3 4 5 6 7)))\n (print (cadddr lst))\n (print (list-ref lst 3)))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Both expressions in let will print number ",(0,r.jsx)(n.code,{children:"4"})," which is the 4th element of the list."]}),"\n",(0,r.jsx)(n.h3,{id:"iterating-over-a-list-recursively",children:"Iterating over a list recursively"}),"\n",(0,r.jsx)(n.p,{children:"This is the basic pattern you use to iterate over a list using recursion:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (operation lst)\n (if (null? lst)\n ...\n (operation (cdr lst))))\n\n"})}),"\n",(0,r.jsx)(n.p,{children:"Here is an example of a function that check if an element is present in the list:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (contains item lst)\n (if (null? lst)\n #f\n (if (equal? item (car lst))\n #t\n (contains item (cdr lst)))))\n\n\n(let ((lst '(1 2 3 4 5 6 0 7 8 9)))\n (print (contains 0 lst)))\n;; ==> #t\n\n(let ((lst '(1 2 3 4 5 6 0 7 8 9)))\n (print (contains \"x\" lst)))\n;; ==> #f\n"})}),"\n",(0,r.jsx)(n.h3,{id:"alists",children:"Alists"}),"\n",(0,r.jsx)(n.p,{children:"Alists (or Association list) is a way to create objects in Scheme using lists. The alist is created with\nlist of cons cells:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(list (cons "x" 10) (cons "y" 20) (cons "z" 30))\n;; ==> (("x" . 10) ("y" . 20) ("z" . 30))\n'})}),"\n",(0,r.jsx)(n.p,{children:"You can also create alist using quotation:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'\'(("x" . 10) ("y" . 20) ("z" . 30))\n'})}),"\n",(0,r.jsx)(n.p,{children:"You have 3 functions that operate on alists:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assq"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"assoc"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The return pair that match first argument or ",(0,r.jsx)(n.code,{children:"#f"})," if not found. The alist is passed as second\nargument. They use ",(0,r.jsx)(n.code,{children:"eq?"}),", ",(0,r.jsx)(n.code,{children:"eqv?"}),", and ",(0,r.jsx)(n.code,{children:"equal?"})," respectively."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x '((foo . 10) (bar . 20) (baz . 30))))\n (print (assoc 'bar x))\n (print (assoc 'quux x)))\n;; ==> (bar . 20)\n;; ==> #f\n"})}),"\n",(0,r.jsxs)(n.p,{children:["First call will return pair ",(0,r.jsx)(n.code,{children:"(bar . 20)"})," because its ",(0,r.jsx)(n.code,{children:"bar"})," symbol is present in the alist. And the\nsecond call will print ",(0,r.jsx)(n.code,{children:"#f"}),"."]}),"\n",(0,r.jsxs)(n.p,{children:["You can use ",(0,r.jsx)(n.code,{children:"cond"})," expression with ",(0,r.jsx)(n.code,{children:"=>"})," syntax to get the value of alist:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let* ((alist '((foo . 10) (bar . 20) (baz . 30)))\n (result (cond ((assoc 'bar alist) => cdr)\n (else '()))))\n (if result\n (print result)))\n;; ==> 20\n"})}),"\n",(0,r.jsx)(n.h2,{id:"finding-element-in-the-list",children:"Finding element in the list"}),"\n",(0,r.jsx)(n.p,{children:"Similar to operation on alist there are 3 functions that find if the element is present in the normal list"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"memq"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"memv"})}),"\n",(0,r.jsx)(n.li,{children:(0,r.jsx)(n.code,{children:"member"})}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["The return cons cell where ",(0,r.jsx)(n.code,{children:"car"})," match object passed as first argument or #f if not found:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(1 2 3 x y z)))\n (print (member 'x lst))\n (print (member 'foo lst)))\n;; ==> (x y z)\n;; ==> #f\n"})}),"\n",(0,r.jsx)(n.h2,{id:"vector-operations",children:"Vector operations"}),"\n",(0,r.jsx)(n.p,{children:"Same as operation on list you can operate on list, you have different procedure to operate on vectors."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((v (vector #\\h #\\e #\\l #\\l #\\o)))\n (write (vector-ref v 0))\n (newline)\n (vector-set! v 0 #\\H)\n (write (vector-ref v 0))\n (newline)\n (print (vector->string v))\n (newline))\n;; ==> #\\h\n;; ==> #\\H\n;; ==> Hello\n"})}),"\n",(0,r.jsxs)(n.p,{children:["To check if an option is a vector, you can use ",(0,r.jsx)(n.code,{children:"vector?"})," predicate."]}),"\n",(0,r.jsx)(n.h2,{id:"string-operations",children:"String operations"}),"\n",(0,r.jsx)(n.p,{children:"Similar to operation on vectors and lists, you have procedures to operate on strings."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(let ((str (string #\\h #\\e #\\l #\\l #\\o)))\n (write (string-ref str 0))\n (newline)\n (string-set! str 0 #\\H)\n (write (string-ref str 0))\n (newline)\n (write str)\n (newline))\n;; ==> #\\h\n;; ==> #\\H\n;; ==> "Hello"\n'})}),"\n",(0,r.jsxs)(n.p,{children:["To check if an object is a string, you can use ",(0,r.jsx)(n.code,{children:"string?"})," predicate."]}),"\n",(0,r.jsx)(n.h2,{id:"multiple-values",children:"Multiple values"}),"\n",(0,r.jsxs)(n.p,{children:["By default, functions in Scheme return a single value, but you can return multiple values with ",(0,r.jsx)(n.code,{children:"values"})," expression."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (div-mul x y)\n (values (/ x y) (* x y)))\n\n(define (plus-minus x y)\n (values (+ x y) (- x y)))\n\n(display (div-mul 2 10))\n;; ==> 1/5 20\n(display (plus-minus 2 10))\n;; ==> 12 -8\n"})}),"\n",(0,r.jsx)(n.p,{children:"When you try to use this value in expression:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x (div-mul 2 10)))\n (display (* x 2)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"Some Scheme implementation will evaluate that expression and get the first value. And some\nimplementation will throw an error about expecting number but got multiple values."}),"\n",(0,r.jsxs)(n.p,{children:["To safety access both values, you can use ",(0,r.jsx)(n.code,{children:"call-with-values"})," procedure:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(call-with-values (lambda () (div-mul 2 10))\n (lambda (div mul)\n (display div)\n (newline)\n (display mul)\n (newline)))\n;; ==> 1/5\n;; ==> 20\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You also have ",(0,r.jsx)(n.code,{children:"let-values"})," and ",(0,r.jsx)(n.code,{children:"let*-values"})," expressions, that works similar to ",(0,r.jsx)(n.code,{children:"let"})," and ",(0,r.jsx)(n.code,{children:"let*"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let-values (((plus minus) (plus-minus 2 10))\n ((div mul) (div-mul 2 10)))\n (+ div mul plus minus))\n;; ==> 121/5\n"})}),"\n",(0,r.jsx)(n.p,{children:"Note that there are two open parentheses before div. The pair is like with let:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let ((x (div-mul 2 10)))\n ...)\n"})}),"\n",(0,r.jsxs)(n.p,{children:["And instead of ",(0,r.jsx)(n.code,{children:"x"})," you have a list with two values that came from ",(0,r.jsx)(n.code,{children:"values"})," expression."]}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"let-values"})," also accept normal (single value expression like ",(0,r.jsx)(n.code,{children:"let"}),") so you can mix them.\nSingle expression still need to be a list but with a single value."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(let*-values (((x) 2)\n ((y) 10)\n ((div mul) (div-mul x y)))\n (+ div mul))\n;; ==> 101/5\n"})}),"\n",(0,r.jsx)(n.h2,{id:"higher-order-functions",children:"Higher order functions"}),"\n",(0,r.jsxs)(n.p,{children:["Functions in Scheme are ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/First-class_citizen",children:"first class"}),", which\nmeans that are the same as any other values like numbers. And can be passed around. You can create a\nfunction that accept other function or create a function that return a function. Functions that\noperate on functions are called ",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Higher-order_function",children:"higher order\nfunctions"})," or higher order procedures."]}),"\n",(0,r.jsxs)(n.p,{children:["Scheme define few built in higher order functions like ",(0,r.jsx)(n.code,{children:"map"}),", ",(0,r.jsx)(n.code,{children:"for-each"})," they both accept a function\nand execute them for every element of the list. ",(0,r.jsx)(n.code,{children:"map"})," return new list from the values and ",(0,r.jsx)(n.code,{children:"for-each"}),"\nreturn unspecified value."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(map square '(1 2 3 4))\n;; ==> (1 4 9 16)\n(map (lambda (x) (* x 10)) '(1 2 3 4))\n;; ==> (10 20 30 40)\n"})}),"\n",(0,r.jsx)(n.p,{children:"You can also define your own higher order functions:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (filter fn lst)\n (if (null? lst)\n '()\n (let ((item (car lst)))\n (if (fn item)\n (cons item (filter fn (cdr lst)))\n (filter fn (cdr lst))))))\n\n(filter odd? '(1 2 3 4 5))\n;; ==> (1 3 5)\n(filter (lambda (x) (not (zero? x))) '(1 2 0 3 0 0 0 4 5 0 6 7))\n;; ==> (1 2 3 4 5 6 7)\n"})}),"\n",(0,r.jsx)(n.p,{children:"You can use function that return lambda to create different list accessors for elements more than 4."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (list-selector n)\n (lambda (list)\n (list-ref list n)))\n\n(define first car)\n(define rest cdr)\n(define second cadr)\n(define third caddr)\n(define fourth cadddr)\n(define fifth (list-selector 4))\n(define sixth (list-selector 5))\n(define seventh (list-selector 6))\n(define eighth (list-selector 7))\n(define ninth (list-selector 8))\n(define tenth (list-selector 9))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Another useful procedure is ",(0,r.jsx)(n.code,{children:"alist-map"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (alist-map fun alist)\n (map (lambda (item) (fun (car item) (cdr item))) alist))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["You can use this procedure to map over values or keys inside an ",(0,r.jsx)(n.a,{href:"#alists",children:"alist"}),"."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define alist (map cons '(a b c d) '(1 2 3 4)))\n\n(alist-map (lambda (key value) (cons key (* value 10))) alist)\n;; ==> ((a . 10) (b . 20) (c . 30) (d . 40))\n(define (symbol-upcase symbol)\n (string->symbol (string-upcase (symbol->string symbol))))\n\n(alist-map (lambda (key value) (cons (symbol-upcase key) value)) alist)\n;; ==> ((A . 1) (B . 2) (C . 3) (D . 4))\n"})}),"\n",(0,r.jsx)(n.h2,{id:"closures",children:"Closures"}),"\n",(0,r.jsx)(n.p,{children:"Scheme have lexical scope. Which means that if functions don't define a variable Scheme search them\noutside in the place where procedure was defined. This allows to create closures. Which are basically\nfunctions that have access to variables defined outside. Scheme need to keep environment in where\nprocedure was defined together with a procedure."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define counter (let ((count 0))\n (lambda ()\n (set! count (+ count 1))\n count)))\n"})}),"\n",(0,r.jsx)(n.p,{children:"This creates a function that have access to a variable defined outside in let expression."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(counter)\n;; ==> 1\n(counter)\n;; ==> 2\n(counter)\n;; ==> 3\n"})}),"\n",(0,r.jsx)(n.p,{children:"With this, you can create functions that create counters that start with a given number:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define (make-counter n)\n (let ((count n))\n (lambda ()\n (set! count (+ count 1))\n count)))\n\n(define counter-1 (make-counter 100))\n(define counter-2 (make-counter 0))\n\n(counter-1)\n;; ==> 101\n(counter-1)\n;; ==> 102\n(counter-2)\n;; ==> 1\n(counter-1)\n;; ==> 103\n(counter-2)\n;; ==> 2\n"})}),"\n",(0,r.jsx)(n.p,{children:"Each counter has its own local state and its own counter variable."}),"\n",(0,r.jsx)(n.h2,{id:"objects",children:"Objects"}),"\n",(0,r.jsx)(n.p,{children:"In Scheme you can have objects (data with behavior), the base code for objects use closures."}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(define (make-person name age)\n (lambda (action . rest)\n (case action\n ((name) name)\n ((age) age)\n ((set-name) (set! name (car rest)))\n ((set-age) (set! age (car rest))))))\n\n(let ((jack (make-person "Jack" 22)))\n (display (jack \'name))\n (newline)\n (jack \'set-name "Mark")\n (jack \'set-age 24)\n (display (jack \'name))\n (display " is ")\n (display (jack \'age))\n (display " years old"))\n;; ==> Jack\n;; ==> Mark is 24 years old\n'})}),"\n",(0,r.jsxs)(n.p,{children:["Notice that it's function which returns a function (",(0,r.jsx)(n.code,{children:"lambda"}),"). You can send a message into that object,\nit will process it by returning a value from closure or mutating that value."]}),"\n",(0,r.jsxs)(n.p,{children:["In the same way you can use ",(0,r.jsx)(n.a,{href:"#alists",children:"alist"}),"."]}),"\n",(0,r.jsx)(n.h3,{id:"records",children:"Records"}),"\n",(0,r.jsxs)(n.p,{children:["Anther way to create objects in Scheme, are R",(0,r.jsx)("sup",{children:"7"}),"RS records, they were first defined in\n",(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-9",children:"SRFI-9"})," and included in the official standard."]}),"\n",(0,r.jsx)(n.p,{children:"You can define records that represent cons cells to create linked lists:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define-record-type :pare\n (kons x y)\n pare?\n (x kar set-kar!)\n (y kdr))\n"})}),"\n",(0,r.jsx)(n.p,{children:"The record type is defined with:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"constructor"}),"\n",(0,r.jsx)(n.li,{children:"predicate that test if the element is of given type"}),"\n",(0,r.jsx)(n.li,{children:"and list of fields"}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"You can use this record like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(define k (kons 1 2))\n(pare? k)\n;; ==> #t\n(kar k)\n;; ==> 1\n(kdr k)\n;; ==> 2\n(set-kar! k 2)\n(cons (kar k) (kdr k))\n;; ==> (2 . 2)\n\n(define (klist . args)\n (if (null? args)\n ()\n (kons (car args) (apply klist (cdr args)))))\n\n(define (kprint klist)\n (display "(")\n (let loop ((klist klist))\n (when (not (null? klist))\n (display (kar klist))\n (let ((rest (kdr klist)))\n (unless (null? rest)\n (display " ")\n (loop rest)))))\n (display ")"))\n\n(define kl (klist 1 2 3 4))\n\n(kar (kdr (kdr (kdr kl))))\n;; ==> 4\n\n(kprint kl)\n;; ==> (1 2 3 4)\n'})}),"\n",(0,r.jsx)(n.h2,{id:"dynamic-variables",children:"Dynamic variables"}),"\n",(0,r.jsxs)(n.p,{children:["Even that Scheme has lexical scope, you can define dynamic variables. They are the opposite of\nlexical variables. When you define a dynamic variable, Scheme will search for them not in the place\nwhere function is defined, but in the place where it's called. That's why if you have fully dynamic lisp\nyou can't have closures. Unless you can somehow add lexical variables. This is the case of\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Emacs_Lisp",children:"Emacs Lisp"}),", lisp that is embedded into an\n",(0,r.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/Emacs",children:"Emacs editor"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"To create dynamic variable in Scheme, you can code like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define x (make-parameter 0))\n\n(define (add-x y)\n (+ (x) y))\n\n(add-x 10)\n;; ==> 10\n(parameterize ((x 10))\n (add-x 10))\n;; ==> 20\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Parameters works like procedures. Do define new dynamic parameter you use ",(0,r.jsx)(n.code,{children:"make-parameter"})," and to\nchange its value you can use ",(0,r.jsx)(n.code,{children:"parameterize"})," that works like ",(0,r.jsx)(n.code,{children:"let"}),". You can also call the parameter\nwith different value and the parameter will use this value as default."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(x 10)\n(add-x 10)\n;; ==> 20\n(parameterize ((x 3))\n (add-x 3))\n;; ==> 6\n"})}),"\n",(0,r.jsx)(n.h2,{id:"loading-of-external-code",children:"Loading of external code"}),"\n",(0,r.jsxs)(n.p,{children:["You can execute external code inside Scheme by using ",(0,r.jsx)(n.code,{children:"load"})," procedure."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:'(load "file.scm")\n'})}),"\n",(0,r.jsxs)(n.p,{children:["This will load an external file named ",(0,r.jsx)(n.code,{children:"file.scm"}),". Scheme files often end with ",(0,r.jsx)(n.code,{children:"scm"}),", but different\nscheme implementation may use different convention."]}),"\n",(0,r.jsx)(n.h2,{id:"eval",children:"Eval"}),"\n",(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"eval"})," procedure is used to evaluate code that is written as data."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define expr '(+ 1 2))\n(eval expr)\n;; ==> 3\n"})}),"\n",(0,r.jsx)(n.p,{children:"Some scheme implementation may require to specify second argument which is environment."}),"\n",(0,r.jsx)(n.p,{children:"You can use those procedures to get different environments:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"(interaction-environment)"})," - this return environment for the REPL"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"(scheme-report-environment )"})," - creates environment with functions from a given\nR",(0,r.jsx)("sup",{children:"n"}),"RS specification"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"scheme-libraries",children:"Scheme libraries"}),"\n",(0,r.jsxs)(n.p,{children:["R",(0,r.jsx)("sup",{children:"7"}),"RS standard of Scheme also define a way to define libraries. This is a common way to\ncreate modules that can be used inside your project or my other people."]}),"\n",(0,r.jsxs)(n.p,{children:["To import a library that is part of the scheme implementation, you use ",(0,r.jsx)(n.code,{children:"import"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(import (srfi 1))\n\n(zip '(1 2 3)\n '(foo bar baz)\n '(one two three))\n;; ==> ((1 foo one) (2 bar two) (3 baz three))\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-1/srfi-1.html",children:"SRFI-1"})," is SRFI that defines a library of procedures\nthat operate on lists (like ",(0,r.jsx)(n.code,{children:"zip"})," procedure that join multiple lists)."]}),"\n",(0,r.jsxs)(n.p,{children:["You can define your own libraries with ",(0,r.jsx)(n.code,{children:"define-library"})," expression:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(define-library (example factorial)\n (export !)\n (import (scheme base))\n (begin\n (define (range n)\n (let loop ((n n) (result '()))\n (if (<= n 0)\n result\n (loop (- n 1) (cons n result)))))\n (define (! n)\n (apply * (range n)))))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["This is definition of library ",(0,r.jsx)(n.code,{children:"(example factorial)"})," that define single procedure ",(0,r.jsx)(n.code,{children:"!"})," that calculate\nfactorial of a number. It defines helper hidden (not exported) procedure ",(0,r.jsx)(n.code,{children:"range"})," that creates a list\nof numbers from ",(0,r.jsx)(n.code,{children:"1"})," to ",(0,r.jsx)(n.code,{children:"n"}),"."]}),"\n",(0,r.jsx)(n.p,{children:"You can use this library like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(import (example factorial))\n(! 10)\n;; ==> 3628800\n"})}),"\n",(0,r.jsx)(n.h2,{id:"portable-code",children:"Portable code"}),"\n",(0,r.jsxs)(n.p,{children:["Scheme implementation differ. And it's hard to write code that will work on multiple Scheme\nInterpreters. Luckily in ",(0,r.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-0/srfi-0.html",children:"SRFI-0"})," (first SRFI ever\ncreated). There is defined special syntax called ",(0,r.jsx)(n.code,{children:"cond-expand"}),". A lot of Scheme implementations have\nthis SRFI built-in so you can use it to detect different Scheme and create code that will match that\nImplementation."]}),"\n",(0,r.jsx)(n.p,{children:"You can use it like this:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(cond-expand\n (kawa)\n (guile)\n (lips)\n (gauche)\n (else))\n"})}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"cond-expand"})," have list of lists in format ",(0,r.jsx)(n.code,{children:"(identifier . code)"}),". For example, if you want to add\n",(0,r.jsx)(n.code,{children:"print"})," function that is defined in ",(0,r.jsx)(n.code,{children:"LIPS"}),", but not in other implementations, you can use code like\nthis:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-scheme",children:"(cond-expand\n (lips)\n (else\n (define (print . args)\n (for-each (lambda (arg)\n (display arg)\n (newline))\n args))\n (define (lips.parse expr)\n (with-input-from-port (open-input-string expr)\n (lambda ()\n (do ((result '() (cons (read) result)))\n ((eof-object? (peek-char)) (list->vector (reverse result)))))))))\n"})}),"\n",(0,r.jsxs)(n.p,{children:["It will evaluate an empty list for ",(0,r.jsx)(n.code,{children:"LIPS"})," and ",(0,r.jsx)(n.code,{children:"define"})," a new ",(0,r.jsx)(n.code,{children:"print"})," and ",(0,r.jsx)(n.code,{children:"lips.parse"})," procedures for\nother implementations. Those procedures are part of LIPS Scheme, see ",(0,r.jsx)(n.a,{href:"/docs/lips/intro",children:"LIPS\nTutorial"}),". Some Scheme implementations may not support ",(0,r.jsx)(n.code,{children:"with-input-from-port"}),"\n(like GNU Kawa) so it may require to add implementation for it."]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(o,{...e})}):o(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>a,x:()=>c});var i=s(6540);const r={},l=i.createContext(r);function a(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.8d4e6b91.js b/assets/js/runtime~main.4bc24965.js similarity index 98% rename from assets/js/runtime~main.8d4e6b91.js rename to assets/js/runtime~main.4bc24965.js index 260d87ba..b933e7ec 100644 --- a/assets/js/runtime~main.8d4e6b91.js +++ b/assets/js/runtime~main.4bc24965.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,c,r,f={},b={};function d(e){var a=b[e];if(void 0!==a)return a.exports;var t=b[e]={exports:{}};return f[e].call(t.exports,t,t.exports,d),t.exports}d.m=f,e=[],d.O=(a,t,c,r)=>{if(!t){var f=1/0;for(i=0;i=r)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(b=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[t,c,r]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var r=Object.create(null);d.r(r);var f={};a=a||[null,t({}),t([]),t(t)];for(var b=2&c&&e;"object"==typeof b&&!~a.indexOf(b);b=t(b))Object.getOwnPropertyNames(b).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,d.d(r,f),r},d.d=(e,a)=>{for(var t in a)d.o(a,t)&&!d.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,t)=>(d.f[t](e,a),a)),[])),d.u=e=>"assets/js/"+({360:"b62caabb",478:"840797c7",849:"0058b4c6",1235:"a7456010",1903:"acecf23e",1933:"35ee46b0",2272:"69aa9e93",2301:"6d18ad6b",2711:"9e4087bc",2866:"61d90f5f",3249:"ccc49370",3484:"13a1c259",3789:"726afaaf",3976:"0e384e19",4044:"92fa5ef1",4212:"621db11d",4413:"e511e452",4583:"1df93b7f",4813:"6875c492",5011:"df5a86e1",5742:"aba21aa0",6271:"f724a01c",6365:"c74dcec5",6372:"7e736cac",6440:"3828c8cd",6580:"0522e7aa",6969:"14eb3368",7098:"a7bd4aaa",7209:"f2e31a35",7350:"6878938b",7472:"814f3328",7643:"a6aa9e1f",7915:"c284b67b",8121:"3a2db09e",8130:"f81c1134",8133:"14a48451",8146:"c15d9823",8177:"e1902777",8209:"01a85c17",8401:"17896441",8649:"413466e5",8691:"ab461798",8947:"ef8b811a",9048:"a94703ab",9067:"5ad8d976",9204:"aa178e2b",9263:"d969d8ea",9397:"68243087",9647:"5e95c892",9651:"4f7497d7",9712:"1ba8abbb",9858:"36994c47"}[e]||e)+"."+{195:"8fd6d84d",360:"aa35aa65",416:"39f57a47",478:"c96b5ad6",849:"0f1f0d46",1235:"35651660",1903:"bd6470b3",1933:"b1a70f61",2237:"66fcbfbc",2272:"2bf1e156",2301:"27284ffb",2711:"c809fcd6",2866:"91265fd4",3249:"83e04d21",3347:"18dfe3b9",3484:"ce796566",3789:"0a3e15cb",3976:"660f9d11",4044:"d15f09bb",4212:"af8ccb67",4413:"ae4b00d1",4583:"916d0087",4813:"1928affb",5011:"3fa53997",5742:"f5d4ac8d",5929:"afb107d6",6271:"53807930",6365:"c648f275",6372:"1cb4ebab",6440:"6d175597",6580:"d85eb94c",6969:"00347ef4",7098:"8794d1bc",7209:"e4dcaeff",7350:"400083d4",7472:"10db33a4",7643:"a3958393",7915:"3ea8b46c",8121:"c1ec56fd",8130:"ba989b8b",8133:"ddb2c881",8146:"024de278",8158:"848e6959",8177:"a8610025",8209:"5200d571",8401:"42d5ed25",8553:"dfe58b8e",8649:"6d557cee",8691:"405f8d17",8913:"a77cc8d9",8947:"e6f6be2e",9048:"d90b76ed",9067:"b56915bc",9204:"c464cf32",9263:"b9446a1b",9397:"bd750e75",9647:"4f997d54",9651:"c16406ad",9712:"26884892",9858:"9727f24b"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},r="new-docs:",d.l=(e,a,t,f)=>{if(c[e])c[e].push(a);else{var b,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var r=c[e];if(delete c[e],b.parentNode&&b.parentNode.removeChild(b),r&&r.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"8401",68243087:"9397",b62caabb:"360","840797c7":"478","0058b4c6":"849",a7456010:"1235",acecf23e:"1903","35ee46b0":"1933","69aa9e93":"2272","6d18ad6b":"2301","9e4087bc":"2711","61d90f5f":"2866",ccc49370:"3249","13a1c259":"3484","726afaaf":"3789","0e384e19":"3976","92fa5ef1":"4044","621db11d":"4212",e511e452:"4413","1df93b7f":"4583","6875c492":"4813",df5a86e1:"5011",aba21aa0:"5742",f724a01c:"6271",c74dcec5:"6365","7e736cac":"6372","3828c8cd":"6440","0522e7aa":"6580","14eb3368":"6969",a7bd4aaa:"7098",f2e31a35:"7209","6878938b":"7350","814f3328":"7472",a6aa9e1f:"7643",c284b67b:"7915","3a2db09e":"8121",f81c1134:"8130","14a48451":"8133",c15d9823:"8146",e1902777:"8177","01a85c17":"8209","413466e5":"8649",ab461798:"8691",ef8b811a:"8947",a94703ab:"9048","5ad8d976":"9067",aa178e2b:"9204",d969d8ea:"9263","5e95c892":"9647","4f7497d7":"9651","1ba8abbb":"9712","36994c47":"9858"}[e]||e,d.p+d.u(e)},(()=>{var e={5354:0,1869:0};d.f.j=(a,t)=>{var c=d.o(e,a)?e[a]:void 0;if(0!==c)if(c)t.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var r=new Promise(((t,r)=>c=e[a]=[t,r]));t.push(c[2]=r);var f=d.p+d.u(a),b=new Error;d.l(f,(t=>{if(d.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var r=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+r+": "+f+")",b.name="ChunkLoadError",b.type=r,b.request=f,c[1](b)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var c,r,f=t[0],b=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(c in b)d.o(b,c)&&(d.m[c]=b[c]);if(o)var i=o(d)}for(a&&a(t);n{"use strict";var e,a,t,c,r,f={},b={};function d(e){var a=b[e];if(void 0!==a)return a.exports;var t=b[e]={exports:{}};return f[e].call(t.exports,t,t.exports,d),t.exports}d.m=f,e=[],d.O=(a,t,c,r)=>{if(!t){var f=1/0;for(i=0;i=r)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(b=!1,r0&&e[i-1][2]>r;i--)e[i]=e[i-1];e[i]=[t,c,r]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var r=Object.create(null);d.r(r);var f={};a=a||[null,t({}),t([]),t(t)];for(var b=2&c&&e;"object"==typeof b&&!~a.indexOf(b);b=t(b))Object.getOwnPropertyNames(b).forEach((a=>f[a]=()=>e[a]));return f.default=()=>e,d.d(r,f),r},d.d=(e,a)=>{for(var t in a)d.o(a,t)&&!d.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,t)=>(d.f[t](e,a),a)),[])),d.u=e=>"assets/js/"+({360:"b62caabb",478:"840797c7",849:"0058b4c6",1235:"a7456010",1903:"acecf23e",1933:"35ee46b0",2272:"69aa9e93",2301:"6d18ad6b",2711:"9e4087bc",2866:"61d90f5f",3249:"ccc49370",3484:"13a1c259",3789:"726afaaf",3976:"0e384e19",4044:"92fa5ef1",4212:"621db11d",4413:"e511e452",4583:"1df93b7f",4813:"6875c492",5011:"df5a86e1",5742:"aba21aa0",6271:"f724a01c",6365:"c74dcec5",6372:"7e736cac",6440:"3828c8cd",6580:"0522e7aa",6969:"14eb3368",7098:"a7bd4aaa",7209:"f2e31a35",7350:"6878938b",7472:"814f3328",7643:"a6aa9e1f",7915:"c284b67b",8121:"3a2db09e",8130:"f81c1134",8133:"14a48451",8146:"c15d9823",8177:"e1902777",8209:"01a85c17",8401:"17896441",8649:"413466e5",8691:"ab461798",8947:"ef8b811a",9048:"a94703ab",9067:"5ad8d976",9204:"aa178e2b",9263:"d969d8ea",9397:"68243087",9647:"5e95c892",9651:"4f7497d7",9712:"1ba8abbb",9858:"36994c47"}[e]||e)+"."+{195:"8fd6d84d",360:"aa35aa65",416:"39f57a47",478:"c96b5ad6",849:"0f1f0d46",1235:"35651660",1903:"bd6470b3",1933:"b1a70f61",2237:"66fcbfbc",2272:"2bf1e156",2301:"27284ffb",2711:"c809fcd6",2866:"91265fd4",3249:"83e04d21",3347:"18dfe3b9",3484:"ce796566",3789:"0a3e15cb",3976:"660f9d11",4044:"d15f09bb",4212:"af8ccb67",4413:"ae4b00d1",4583:"916d0087",4813:"1928affb",5011:"3fa53997",5742:"f5d4ac8d",5929:"afb107d6",6271:"53807930",6365:"c648f275",6372:"1cb4ebab",6440:"6d175597",6580:"d85eb94c",6969:"00347ef4",7098:"8794d1bc",7209:"e4dcaeff",7350:"400083d4",7472:"10db33a4",7643:"a3958393",7915:"3ea8b46c",8121:"c1ec56fd",8130:"ba989b8b",8133:"ddb2c881",8146:"024de278",8158:"848e6959",8177:"a8610025",8209:"5200d571",8401:"42d5ed25",8553:"dfe58b8e",8649:"4bfa6453",8691:"405f8d17",8913:"a77cc8d9",8947:"e6f6be2e",9048:"d90b76ed",9067:"b56915bc",9204:"c464cf32",9263:"b9446a1b",9397:"bd750e75",9647:"4f997d54",9651:"c16406ad",9712:"26884892",9858:"9727f24b"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},r="new-docs:",d.l=(e,a,t,f)=>{if(c[e])c[e].push(a);else{var b,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var r=c[e];if(delete c[e],b.parentNode&&b.parentNode.removeChild(b),r&&r.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"8401",68243087:"9397",b62caabb:"360","840797c7":"478","0058b4c6":"849",a7456010:"1235",acecf23e:"1903","35ee46b0":"1933","69aa9e93":"2272","6d18ad6b":"2301","9e4087bc":"2711","61d90f5f":"2866",ccc49370:"3249","13a1c259":"3484","726afaaf":"3789","0e384e19":"3976","92fa5ef1":"4044","621db11d":"4212",e511e452:"4413","1df93b7f":"4583","6875c492":"4813",df5a86e1:"5011",aba21aa0:"5742",f724a01c:"6271",c74dcec5:"6365","7e736cac":"6372","3828c8cd":"6440","0522e7aa":"6580","14eb3368":"6969",a7bd4aaa:"7098",f2e31a35:"7209","6878938b":"7350","814f3328":"7472",a6aa9e1f:"7643",c284b67b:"7915","3a2db09e":"8121",f81c1134:"8130","14a48451":"8133",c15d9823:"8146",e1902777:"8177","01a85c17":"8209","413466e5":"8649",ab461798:"8691",ef8b811a:"8947",a94703ab:"9048","5ad8d976":"9067",aa178e2b:"9204",d969d8ea:"9263","5e95c892":"9647","4f7497d7":"9651","1ba8abbb":"9712","36994c47":"9858"}[e]||e,d.p+d.u(e)},(()=>{var e={5354:0,1869:0};d.f.j=(a,t)=>{var c=d.o(e,a)?e[a]:void 0;if(0!==c)if(c)t.push(c[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var r=new Promise(((t,r)=>c=e[a]=[t,r]));t.push(c[2]=r);var f=d.p+d.u(a),b=new Error;d.l(f,(t=>{if(d.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var r=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+r+": "+f+")",b.name="ChunkLoadError",b.type=r,b.request=f,c[1](b)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var c,r,f=t[0],b=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(c in b)d.o(b,c)&&(d.m[c]=b[c]);if(o)var i=o(d)}for(a&&a(t);n Blog | LIPS Scheme - + diff --git a/blog/archive.html b/blog/archive.html index ce1d9f78..4ea905fc 100644 --- a/blog/archive.html +++ b/blog/archive.html @@ -4,7 +4,7 @@ Archive | LIPS Scheme - + diff --git a/blog/authors.html b/blog/authors.html index 520f9b97..de7fb5d4 100644 --- a/blog/authors.html +++ b/blog/authors.html @@ -4,7 +4,7 @@ Authors | LIPS Scheme - + diff --git a/blog/emacs-scheme-regex.html b/blog/emacs-scheme-regex.html index 33675aed..29e00cfd 100644 --- a/blog/emacs-scheme-regex.html +++ b/blog/emacs-scheme-regex.html @@ -4,7 +4,7 @@ Scheme Regex literals in Emacs | LIPS Scheme - + diff --git a/blog/lips-history.html b/blog/lips-history.html index 5c894119..806c585a 100644 --- a/blog/lips-history.html +++ b/blog/lips-history.html @@ -4,7 +4,7 @@ LIPS Scheme History | LIPS Scheme - + diff --git a/blog/tags.html b/blog/tags.html index b1288b74..0e7ab248 100644 --- a/blog/tags.html +++ b/blog/tags.html @@ -4,7 +4,7 @@ Tags | LIPS Scheme - + diff --git a/blog/tags/emacs.html b/blog/tags/emacs.html index 32c22af5..bfb6f234 100644 --- a/blog/tags/emacs.html +++ b/blog/tags/emacs.html @@ -4,7 +4,7 @@ One post tagged with "emacs" | LIPS Scheme - + diff --git a/blog/tags/history.html b/blog/tags/history.html index 890dee7e..56eafd56 100644 --- a/blog/tags/history.html +++ b/blog/tags/history.html @@ -4,7 +4,7 @@ One post tagged with "history" | LIPS Scheme - + diff --git a/blog/tags/lips.html b/blog/tags/lips.html index 55407d89..8c4e07ae 100644 --- a/blog/tags/lips.html +++ b/blog/tags/lips.html @@ -4,7 +4,7 @@ One post tagged with "lips" | LIPS Scheme - + diff --git a/blog/tags/scheme.html b/blog/tags/scheme.html index fbf6849b..db9a78e9 100644 --- a/blog/tags/scheme.html +++ b/blog/tags/scheme.html @@ -4,7 +4,7 @@ 2 posts tagged with "scheme" | LIPS Scheme - + diff --git a/docs/category/introduction-to-scheme.html b/docs/category/introduction-to-scheme.html index 7c208070..1f00b01e 100644 --- a/docs/category/introduction-to-scheme.html +++ b/docs/category/introduction-to-scheme.html @@ -4,7 +4,7 @@ Introduction to Scheme | LIPS Scheme - + diff --git a/docs/category/lips-introduction.html b/docs/category/lips-introduction.html index 25d8e517..94afece7 100644 --- a/docs/category/lips-introduction.html +++ b/docs/category/lips-introduction.html @@ -4,7 +4,7 @@ LIPS introduction | LIPS Scheme - + diff --git a/docs/intro.html b/docs/intro.html index 53d0ade8..63a9dd18 100644 --- a/docs/intro.html +++ b/docs/intro.html @@ -4,7 +4,7 @@ Getting Started | LIPS Scheme - + diff --git a/docs/lips/REPL.html b/docs/lips/REPL.html index 89603fe9..dfd62308 100644 --- a/docs/lips/REPL.html +++ b/docs/lips/REPL.html @@ -4,7 +4,7 @@ REPL | LIPS Scheme - + diff --git a/docs/lips/SRFI.html b/docs/lips/SRFI.html index a19ddb3b..d595a3ab 100644 --- a/docs/lips/SRFI.html +++ b/docs/lips/SRFI.html @@ -4,7 +4,7 @@ SRFI | LIPS Scheme - + diff --git a/docs/lips/embeding-repl.html b/docs/lips/embeding-repl.html index 634df091..76dab236 100644 --- a/docs/lips/embeding-repl.html +++ b/docs/lips/embeding-repl.html @@ -4,7 +4,7 @@ Embedding LIPS REPL | LIPS Scheme - + diff --git a/docs/lips/environments.html b/docs/lips/environments.html index f9a0fd90..c7865507 100644 --- a/docs/lips/environments.html +++ b/docs/lips/environments.html @@ -4,7 +4,7 @@ Environments | LIPS Scheme - + diff --git a/docs/lips/extension.html b/docs/lips/extension.html index 8a0f21f7..6895868b 100644 --- a/docs/lips/extension.html +++ b/docs/lips/extension.html @@ -4,7 +4,7 @@ Extending LIPS | LIPS Scheme - + diff --git a/docs/lips/functional-helpers.html b/docs/lips/functional-helpers.html index 3d599ca1..21417d5f 100644 --- a/docs/lips/functional-helpers.html +++ b/docs/lips/functional-helpers.html @@ -4,7 +4,7 @@ Functional and other utils | LIPS Scheme - + diff --git a/docs/lips/intro.html b/docs/lips/intro.html index 0984f12b..df709ae6 100644 --- a/docs/lips/intro.html +++ b/docs/lips/intro.html @@ -4,7 +4,7 @@ Core features | LIPS Scheme - + diff --git a/docs/lips/reflection.html b/docs/lips/reflection.html index 012c7765..d11d38e5 100644 --- a/docs/lips/reflection.html +++ b/docs/lips/reflection.html @@ -4,7 +4,7 @@ Reflection | LIPS Scheme - + diff --git a/docs/lips/sxml.html b/docs/lips/sxml.html index f73e1b7c..33f86360 100644 --- a/docs/lips/sxml.html +++ b/docs/lips/sxml.html @@ -4,7 +4,7 @@ SXML (e.g. for React) | LIPS Scheme - + diff --git a/docs/scheme-intro/continuations.html b/docs/scheme-intro/continuations.html index 0f6dc071..4d41e636 100644 --- a/docs/scheme-intro/continuations.html +++ b/docs/scheme-intro/continuations.html @@ -4,7 +4,7 @@ Continuations | LIPS Scheme - + diff --git a/docs/scheme-intro/core.html b/docs/scheme-intro/core.html index f6ac9db8..69dd9c79 100644 --- a/docs/scheme-intro/core.html +++ b/docs/scheme-intro/core.html @@ -4,7 +4,7 @@ Core of Scheme | LIPS Scheme - + @@ -332,7 +332,7 @@

Optional
(rational 1 2)
 ;; ==> 1/2
 
-

If scheme provide rational numbers, or it will return 0.5 otherwise.

+

If scheme provides rational numbers, or it will return 0.5 otherwise.

Recursion

You can define a function that reference to itself:

(define (factorial n)
diff --git a/docs/scheme-intro/data-types.html b/docs/scheme-intro/data-types.html
index 014c8d9f..cbd725bb 100644
--- a/docs/scheme-intro/data-types.html
+++ b/docs/scheme-intro/data-types.html
@@ -4,7 +4,7 @@
 
 
 Data Types | LIPS Scheme
-
+
 
 
 
diff --git a/docs/scheme-intro/input-output.html b/docs/scheme-intro/input-output.html
index 82c93e15..73144fb9 100644
--- a/docs/scheme-intro/input-output.html
+++ b/docs/scheme-intro/input-output.html
@@ -4,7 +4,7 @@
 
 
 Input and Output | LIPS Scheme
-
+
 
 
 
diff --git a/docs/scheme-intro/macros.html b/docs/scheme-intro/macros.html
index f3794c32..e89f64ce 100644
--- a/docs/scheme-intro/macros.html
+++ b/docs/scheme-intro/macros.html
@@ -4,7 +4,7 @@
 
 
 Macros | LIPS Scheme
-
+
 
 
 
diff --git a/docs/scheme-intro/next-step.html b/docs/scheme-intro/next-step.html
index f6565c96..0856ba35 100644
--- a/docs/scheme-intro/next-step.html
+++ b/docs/scheme-intro/next-step.html
@@ -4,7 +4,7 @@
 
 
 What Next? | LIPS Scheme
-
+
 
 
 
diff --git a/docs/scheme-intro/streams.html b/docs/scheme-intro/streams.html
index f575e1bd..de762419 100644
--- a/docs/scheme-intro/streams.html
+++ b/docs/scheme-intro/streams.html
@@ -4,7 +4,7 @@
 
 
 Streams | LIPS Scheme
-
+
 
 
 
diff --git a/docs/scheme-intro/what-is-lisp.html b/docs/scheme-intro/what-is-lisp.html
index 7a9aa0bd..1aea72d1 100644
--- a/docs/scheme-intro/what-is-lisp.html
+++ b/docs/scheme-intro/what-is-lisp.html
@@ -4,7 +4,7 @@
 
 
 What is Lisp and Scheme? | LIPS Scheme
-
+
 
 
 
diff --git a/index.html b/index.html
index 4e481f1c..4101db8a 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
 
 
 Powerful Scheme interpreter in JavaScript | LIPS Scheme
-
+
 
 
 
diff --git a/reference.html b/reference.html
index 38e8012b..ccc39cad 100644
--- a/reference.html
+++ b/reference.html
@@ -4,7 +4,7 @@
 
 
 Function and Macro Reference | LIPS Scheme
-
+
 
 
 
diff --git a/screenshooter.html b/screenshooter.html
index 561918fe..35b84348 100644
--- a/screenshooter.html
+++ b/screenshooter.html
@@ -4,7 +4,7 @@
 
 
 Screenshooter | LIPS Scheme
-
+
 
 
 
diff --git a/sitemap.xml b/sitemap.xml
index f2ea7b18..05294f89 100644
--- a/sitemap.xml
+++ b/sitemap.xml
@@ -1 +1 @@
-https://lips.js.org/blogweekly0.5https://lips.js.org/blog/archiveweekly0.5https://lips.js.org/blog/authorsweekly0.5https://lips.js.org/blog/emacs-scheme-regex2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/blog/lips-history2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/blog/tagsweekly0.5https://lips.js.org/blog/tags/emacsweekly0.5https://lips.js.org/blog/tags/historyweekly0.5https://lips.js.org/blog/tags/lipsweekly0.5https://lips.js.org/blog/tags/schemeweekly0.5https://lips.js.org/reference2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/screenshooter2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/category/introduction-to-schemeweekly0.5https://lips.js.org/docs/category/lips-introductionweekly0.5https://lips.js.org/docs/intro2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/embeding-repl2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/environments2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/extension2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/functional-helpers2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/intro2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/reflection2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/REPL2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/SRFI2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/lips/sxml2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/continuations2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/core2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/data-types2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/input-output2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/macros2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/next-step2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/streams2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/docs/scheme-intro/what-is-lisp2024-11-14T22:52:17.000Zweekly0.5https://lips.js.org/2024-11-14T22:52:17.000Zweekly0.5
\ No newline at end of file
+https://lips.js.org/blogweekly0.5https://lips.js.org/blog/archiveweekly0.5https://lips.js.org/blog/authorsweekly0.5https://lips.js.org/blog/emacs-scheme-regex2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/blog/lips-history2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/blog/tagsweekly0.5https://lips.js.org/blog/tags/emacsweekly0.5https://lips.js.org/blog/tags/historyweekly0.5https://lips.js.org/blog/tags/lipsweekly0.5https://lips.js.org/blog/tags/schemeweekly0.5https://lips.js.org/reference2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/screenshooter2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/category/introduction-to-schemeweekly0.5https://lips.js.org/docs/category/lips-introductionweekly0.5https://lips.js.org/docs/intro2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/embeding-repl2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/environments2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/extension2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/functional-helpers2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/intro2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/reflection2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/REPL2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/SRFI2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/lips/sxml2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/continuations2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/core2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/data-types2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/input-output2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/macros2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/next-step2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/streams2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/docs/scheme-intro/what-is-lisp2024-11-30T13:47:57.000Zweekly0.5https://lips.js.org/2024-11-30T13:47:57.000Zweekly0.5
\ No newline at end of file