From 559a5b08fd4a3b982db3a7f33a42ceed3d5d9613 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Dec 2024 20:54:57 +0000 Subject: [PATCH] deploy: 0166c181ca98aac61e0992929184658e320546f2 --- 404.html | 2 +- assets/js/0058b4c6.0f1f0d46.js | 1 - assets/js/0058b4c6.e79d03cd.js | 1 + assets/js/13a1c259.c938df1a.js | 1 + assets/js/13a1c259.ce796566.js | 1 - assets/js/840797c7.442699c4.js | 1 + assets/js/840797c7.c96b5ad6.js | 1 - assets/js/e1902777.a8610025.js | 1 - assets/js/e1902777.fcbe341c.js | 1 + .../{runtime~main.20f5ee6a.js => runtime~main.a64e70e2.js} | 2 +- blog.html | 2 +- blog/archive.html | 2 +- blog/authors.html | 2 +- blog/emacs-scheme-regex.html | 2 +- blog/lips-history.html | 2 +- blog/tags.html | 2 +- blog/tags/emacs.html | 2 +- blog/tags/history.html | 2 +- blog/tags/lips.html | 2 +- blog/tags/scheme.html | 2 +- docs/category/introduction-to-scheme.html | 4 ++-- docs/category/lips-introduction.html | 6 +++--- docs/intro.html | 4 ++-- docs/lips/REPL.html | 4 ++-- docs/lips/SRFI.html | 4 ++-- docs/lips/embeding-repl.html | 4 ++-- docs/lips/environments.html | 4 ++-- docs/lips/extension.html | 4 ++-- docs/lips/functional-helpers.html | 4 ++-- docs/lips/intro.html | 6 +++--- docs/lips/reflection.html | 4 ++-- docs/lips/sxml.html | 4 ++-- docs/scheme-intro/continuations.html | 4 ++-- docs/scheme-intro/core.html | 4 ++-- docs/scheme-intro/data-types.html | 4 ++-- docs/scheme-intro/input-output.html | 4 ++-- docs/scheme-intro/macros.html | 4 ++-- docs/scheme-intro/next-step.html | 6 +++--- docs/scheme-intro/streams.html | 4 ++-- docs/scheme-intro/what-is-lisp.html | 4 ++-- index.html | 2 +- reference.html | 2 +- screenshooter.html | 2 +- sitemap.xml | 2 +- 44 files changed, 63 insertions(+), 63 deletions(-) delete mode 100644 assets/js/0058b4c6.0f1f0d46.js create mode 100644 assets/js/0058b4c6.e79d03cd.js create mode 100644 assets/js/13a1c259.c938df1a.js delete mode 100644 assets/js/13a1c259.ce796566.js create mode 100644 assets/js/840797c7.442699c4.js delete mode 100644 assets/js/840797c7.c96b5ad6.js delete mode 100644 assets/js/e1902777.a8610025.js create mode 100644 assets/js/e1902777.fcbe341c.js rename assets/js/{runtime~main.20f5ee6a.js => runtime~main.a64e70e2.js} (65%) diff --git a/404.html b/404.html index 6565c859..d78bd4a4 100644 --- a/404.html +++ b/404.html @@ -4,7 +4,7 @@ Page Not Found | LIPS Scheme - + diff --git a/assets/js/0058b4c6.0f1f0d46.js b/assets/js/0058b4c6.0f1f0d46.js deleted file mode 100644 index dbb5d149..00000000 --- a/assets/js/0058b4c6.0f1f0d46.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[849],{6164:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Getting Started","href":"/docs/intro","docId":"intro","unlisted":false},{"type":"category","label":"Introduction to Scheme","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"What is Lisp and Scheme?","href":"/docs/scheme-intro/what-is-lisp","docId":"scheme-intro/what-is-lisp","unlisted":false},{"type":"link","label":"Data Types","href":"/docs/scheme-intro/data-types","docId":"scheme-intro/data-types","unlisted":false},{"type":"link","label":"Core of Scheme","href":"/docs/scheme-intro/core","docId":"scheme-intro/core","unlisted":false},{"type":"link","label":"Input and Output","href":"/docs/scheme-intro/input-output","docId":"scheme-intro/input-output","unlisted":false},{"type":"link","label":"Macros","href":"/docs/scheme-intro/macros","docId":"scheme-intro/macros","unlisted":false},{"type":"link","label":"Streams","href":"/docs/scheme-intro/streams","docId":"scheme-intro/streams","unlisted":false},{"type":"link","label":"Continuations","href":"/docs/scheme-intro/continuations","docId":"scheme-intro/continuations","unlisted":false},{"type":"link","label":"What Next?","href":"/docs/scheme-intro/next-step","docId":"scheme-intro/next-step","unlisted":false}],"href":"/docs/category/introduction-to-scheme"},{"type":"category","label":"LIPS introduction","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Core features","href":"/docs/lips/intro","docId":"lips/intro","unlisted":false},{"type":"link","label":"Reflection","href":"/docs/lips/reflection","docId":"lips/reflection","unlisted":false},{"type":"link","label":"SXML (e.g. for React)","href":"/docs/lips/sxml","docId":"lips/sxml","unlisted":false},{"type":"link","label":"Environments","href":"/docs/lips/environments","docId":"lips/environments","unlisted":false},{"type":"link","label":"Functional and other utils","href":"/docs/lips/functional-helpers","docId":"lips/functional-helpers","unlisted":false},{"type":"link","label":"Extending LIPS","href":"/docs/lips/extension","docId":"lips/extension","unlisted":false},{"type":"link","label":"REPL","href":"/docs/lips/REPL","docId":"lips/REPL","unlisted":false},{"type":"link","label":"SRFI","href":"/docs/lips/SRFI","docId":"lips/SRFI","unlisted":false},{"type":"link","label":"Embedding LIPS REPL","href":"/docs/lips/embeding-repl","docId":"lips/embeding-repl","unlisted":false}],"href":"/docs/category/lips-introduction"}]},"docs":{"intro":{"id":"intro","title":"Getting Started","description":"Browser","sidebar":"tutorialSidebar"},"lips/embeding-repl":{"id":"lips/embeding-repl","title":"Embedding LIPS REPL","description":"Embedding the LIPS Scheme REPL","sidebar":"tutorialSidebar"},"lips/environments":{"id":"lips/environments","title":"Environments","description":"Environments in LIPS are first class objects","sidebar":"tutorialSidebar"},"lips/extension":{"id":"lips/extension","title":"Extending LIPS","description":"A way to extends LIPS syntax, not only with macros","sidebar":"tutorialSidebar"},"lips/functional-helpers":{"id":"lips/functional-helpers","title":"Functional and other utils","description":"Code that allows to do more with less","sidebar":"tutorialSidebar"},"lips/intro":{"id":"lips/intro","title":"Core features","description":"Core LIPS features added on top of Scheme, related to JavaScript","sidebar":"tutorialSidebar"},"lips/reflection":{"id":"lips/reflection","title":"Reflection","description":"A way to introspect and manipulate LIPS internals","sidebar":"tutorialSidebar"},"lips/REPL":{"id":"lips/REPL","title":"REPL","description":"features of Node.js and Web REPL","sidebar":"tutorialSidebar"},"lips/SRFI":{"id":"lips/SRFI","title":"SRFI","description":"List of supported SRFI","sidebar":"tutorialSidebar"},"lips/sxml":{"id":"lips/sxml","title":"SXML (e.g. for React)","description":"SXML it\'s what JSX is for JavaScript","sidebar":"tutorialSidebar"},"scheme-intro/continuations":{"id":"scheme-intro/continuations","title":"Continuations","description":"Powerful feature of Scheme that allow to add new control flows","sidebar":"tutorialSidebar"},"scheme-intro/core":{"id":"scheme-intro/core","title":"Core of Scheme","description":"Main article that shows most of the features of Scheme","sidebar":"tutorialSidebar"},"scheme-intro/data-types":{"id":"scheme-intro/data-types","title":"Data Types","description":"All different data types you can have in Scheme","sidebar":"tutorialSidebar"},"scheme-intro/input-output":{"id":"scheme-intro/input-output","title":"Input and Output","description":"How to read/write files and how to interact with stdin/stdout","sidebar":"tutorialSidebar"},"scheme-intro/macros":{"id":"scheme-intro/macros","title":"Macros","description":"Macros are the most powerful feature of Lisp and Scheme","sidebar":"tutorialSidebar"},"scheme-intro/next-step":{"id":"scheme-intro/next-step","title":"What Next?","description":"Few resources how to learn more about Scheme","sidebar":"tutorialSidebar"},"scheme-intro/streams":{"id":"scheme-intro/streams","title":"Streams","description":"Feature of scheme that allow to create lazy lists","sidebar":"tutorialSidebar"},"scheme-intro/what-is-lisp":{"id":"scheme-intro/what-is-lisp","title":"What is Lisp and Scheme?","description":"What is Lisp and what is Scheme and a bit of history","sidebar":"tutorialSidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/0058b4c6.e79d03cd.js b/assets/js/0058b4c6.e79d03cd.js new file mode 100644 index 00000000..8c695c50 --- /dev/null +++ b/assets/js/0058b4c6.e79d03cd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[849],{6164:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"link","label":"Getting Started","href":"/docs/intro","docId":"intro","unlisted":false},{"type":"category","label":"Introduction to Scheme","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"What is Lisp and Scheme?","href":"/docs/scheme-intro/what-is-lisp","docId":"scheme-intro/what-is-lisp","unlisted":false},{"type":"link","label":"Data Types","href":"/docs/scheme-intro/data-types","docId":"scheme-intro/data-types","unlisted":false},{"type":"link","label":"Core of Scheme","href":"/docs/scheme-intro/core","docId":"scheme-intro/core","unlisted":false},{"type":"link","label":"Input and Output","href":"/docs/scheme-intro/input-output","docId":"scheme-intro/input-output","unlisted":false},{"type":"link","label":"Macros","href":"/docs/scheme-intro/macros","docId":"scheme-intro/macros","unlisted":false},{"type":"link","label":"Streams","href":"/docs/scheme-intro/streams","docId":"scheme-intro/streams","unlisted":false},{"type":"link","label":"Continuations","href":"/docs/scheme-intro/continuations","docId":"scheme-intro/continuations","unlisted":false},{"type":"link","label":"What Next?","href":"/docs/scheme-intro/next-step","docId":"scheme-intro/next-step","unlisted":false}],"href":"/docs/category/introduction-to-scheme"},{"type":"category","label":"LIPS Documentation","collapsible":true,"collapsed":true,"items":[{"type":"link","label":"Core features","href":"/docs/lips/intro","docId":"lips/intro","unlisted":false},{"type":"link","label":"Reflection","href":"/docs/lips/reflection","docId":"lips/reflection","unlisted":false},{"type":"link","label":"SXML (e.g. for React)","href":"/docs/lips/sxml","docId":"lips/sxml","unlisted":false},{"type":"link","label":"Environments","href":"/docs/lips/environments","docId":"lips/environments","unlisted":false},{"type":"link","label":"Functional and other utils","href":"/docs/lips/functional-helpers","docId":"lips/functional-helpers","unlisted":false},{"type":"link","label":"Extending LIPS","href":"/docs/lips/extension","docId":"lips/extension","unlisted":false},{"type":"link","label":"REPL","href":"/docs/lips/REPL","docId":"lips/REPL","unlisted":false},{"type":"link","label":"SRFI","href":"/docs/lips/SRFI","docId":"lips/SRFI","unlisted":false},{"type":"link","label":"Embedding LIPS REPL","href":"/docs/lips/embeding-repl","docId":"lips/embeding-repl","unlisted":false}],"href":"/docs/category/lips-introduction"}]},"docs":{"intro":{"id":"intro","title":"Getting Started","description":"Browser","sidebar":"tutorialSidebar"},"lips/embeding-repl":{"id":"lips/embeding-repl","title":"Embedding LIPS REPL","description":"Embedding the LIPS Scheme REPL","sidebar":"tutorialSidebar"},"lips/environments":{"id":"lips/environments","title":"Environments","description":"Environments in LIPS are first class objects","sidebar":"tutorialSidebar"},"lips/extension":{"id":"lips/extension","title":"Extending LIPS","description":"A way to extends LIPS syntax, not only with macros","sidebar":"tutorialSidebar"},"lips/functional-helpers":{"id":"lips/functional-helpers","title":"Functional and other utils","description":"Code that allows to do more with less","sidebar":"tutorialSidebar"},"lips/intro":{"id":"lips/intro","title":"Core features","description":"Core LIPS features added on top of Scheme, related to JavaScript","sidebar":"tutorialSidebar"},"lips/reflection":{"id":"lips/reflection","title":"Reflection","description":"A way to introspect and manipulate LIPS internals","sidebar":"tutorialSidebar"},"lips/REPL":{"id":"lips/REPL","title":"REPL","description":"features of Node.js and Web REPL","sidebar":"tutorialSidebar"},"lips/SRFI":{"id":"lips/SRFI","title":"SRFI","description":"List of supported SRFI","sidebar":"tutorialSidebar"},"lips/sxml":{"id":"lips/sxml","title":"SXML (e.g. for React)","description":"SXML it\'s what JSX is for JavaScript","sidebar":"tutorialSidebar"},"scheme-intro/continuations":{"id":"scheme-intro/continuations","title":"Continuations","description":"Powerful feature of Scheme that allow to add new control flows","sidebar":"tutorialSidebar"},"scheme-intro/core":{"id":"scheme-intro/core","title":"Core of Scheme","description":"Main article that shows most of the features of Scheme","sidebar":"tutorialSidebar"},"scheme-intro/data-types":{"id":"scheme-intro/data-types","title":"Data Types","description":"All different data types you can have in Scheme","sidebar":"tutorialSidebar"},"scheme-intro/input-output":{"id":"scheme-intro/input-output","title":"Input and Output","description":"How to read/write files and how to interact with stdin/stdout","sidebar":"tutorialSidebar"},"scheme-intro/macros":{"id":"scheme-intro/macros","title":"Macros","description":"Macros are the most powerful feature of Lisp and Scheme","sidebar":"tutorialSidebar"},"scheme-intro/next-step":{"id":"scheme-intro/next-step","title":"What Next?","description":"Few resources how to learn more about Scheme","sidebar":"tutorialSidebar"},"scheme-intro/streams":{"id":"scheme-intro/streams","title":"Streams","description":"Feature of scheme that allow to create lazy lists","sidebar":"tutorialSidebar"},"scheme-intro/what-is-lisp":{"id":"scheme-intro/what-is-lisp","title":"What is Lisp and Scheme?","description":"What is Lisp and what is Scheme and a bit of history","sidebar":"tutorialSidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/13a1c259.c938df1a.js b/assets/js/13a1c259.c938df1a.js new file mode 100644 index 00000000..c9e94185 --- /dev/null +++ b/assets/js/13a1c259.c938df1a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[3484],{3202:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"LIPS Documentation","slug":"/category/lips-introduction","permalink":"/docs/category/lips-introduction","sidebar":"tutorialSidebar","navigation":{"previous":{"title":"What Next?","permalink":"/docs/scheme-intro/next-step"},"next":{"title":"Core features","permalink":"/docs/lips/intro"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/13a1c259.ce796566.js b/assets/js/13a1c259.ce796566.js deleted file mode 100644 index 395dc88f..00000000 --- a/assets/js/13a1c259.ce796566.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[3484],{3202:e=>{e.exports=JSON.parse('{"categoryGeneratedIndex":{"title":"LIPS introduction","slug":"/category/lips-introduction","permalink":"/docs/category/lips-introduction","sidebar":"tutorialSidebar","navigation":{"previous":{"title":"What Next?","permalink":"/docs/scheme-intro/next-step"},"next":{"title":"Core features","permalink":"/docs/lips/intro"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/840797c7.442699c4.js b/assets/js/840797c7.442699c4.js new file mode 100644 index 00000000..82a5b99f --- /dev/null +++ b/assets/js/840797c7.442699c4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[478],{3055:(e,A,s)=>{s.r(A),s.d(A,{assets:()=>i,contentTitle:()=>o,default:()=>a,frontMatter:()=>c,metadata:()=>r,toc:()=>h});const r=JSON.parse('{"id":"scheme-intro/next-step","title":"What Next?","description":"Few resources how to learn more about Scheme","source":"@site/docs/scheme-intro/next-step.md","sourceDirName":"scheme-intro","slug":"/scheme-intro/next-step","permalink":"/docs/scheme-intro/next-step","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/scheme-intro/next-step.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"sidebar_position":8,"description":"Few resources how to learn more about Scheme"},"sidebar":"tutorialSidebar","previous":{"title":"Continuations","permalink":"/docs/scheme-intro/continuations"},"next":{"title":"LIPS Documentation","permalink":"/docs/category/lips-introduction"}}');var n=s(4848),t=s(8453);const c={sidebar_position:8,description:"Few resources how to learn more about Scheme"},o="What Next?",i={},h=[{value:"Scheme",id:"scheme",level:2},{value:"Lisp Macros",id:"lisp-macros",level:2},{value:"Scheme hygienic macros",id:"scheme-hygienic-macros",level:2},{value:"More Resources",id:"more-resources",level:2}];function l(e){const A={a:"a",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(A.header,{children:(0,n.jsx)(A.h1,{id:"what-next",children:"What Next?"})}),"\n",(0,n.jsx)(A.p,{children:"If you want to learn more about Scheme, here are some recommended resources:"}),"\n",(0,n.jsx)(A.h2,{id:"scheme",children:"Scheme"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://www.t3x.org/sketchy/",children:"Sketchy Scheme"})," by ",(0,n.jsx)(A.a,{href:"https://www.t3x.org/",children:"Nils M Holm"})]}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.img,{alt:"Sketchy Scheme Book Cover",src:s(8446).A+"",width:"417",height:"621"})}),"\n",(0,n.jsxs)(A.p,{children:["There is a free version in Archive.org called ",(0,n.jsx)(A.a,{href:"https://archive.org/details/sketchy-lisp",children:"Sketchy Lisp"})," but I recommend latest version."]}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"https://web.mit.edu/6.001/6.037/sicp.pdf",children:"Structure and Interpretation of Computer Programs"})}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:"A classic, one of the authors of the book is the author of Scheme language."}),"\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.img,{alt:"SICP Cover",src:s(2938).A+"",width:"400",height:"579"}),(0,n.jsx)("br",{}),"\n",(0,n.jsxs)("small",{children:[(0,n.jsx)("a",{href:"https://commons.wikimedia.org/wiki/File:SICP_cover.jpg",children:"Harold Abelson and Gerald Jay Sussman with Julie Sussman\xa0\u2014\xa0MIT Press"}),", ",(0,n.jsx)("a",{href:"https://creativecommons.org/licenses/by-sa/4.0",children:"CC BY-SA 4.0"}),", Wikimedia Commons"]})]}),"\n",(0,n.jsx)(A.p,{children:"I also recommend video lectures. There are two versions. I recommend original by Abelson and Sussman from 1986."}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.youtube.com/playlist?list=PLB63C06FAF154F047",children:(0,n.jsx)(A.img,{alt:"SICP MIT Lectures",src:s(234).A+"",width:"320",height:"240"})})}),"\n",(0,n.jsxs)(A.p,{children:["Here is the ",(0,n.jsx)(A.a,{href:"https://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/",children:"official website of the lectures"}),"."]}),"\n",(0,n.jsx)(A.p,{children:"They are not very good quality, but they are great, and you should have no problems in seeing the\ncode on the blackboard."}),"\n",(0,n.jsxs)(A.p,{children:["There are also more recent lectures from 2010 at ",(0,n.jsx)(A.a,{href:"https://www.berkeley.edu/",children:"Berkeley"})," by\n",(0,n.jsx)(A.a,{href:"https://people.eecs.berkeley.edu/~bh/",children:"Brian Harvey"}),". Only a little bit better quality."]}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.youtube.com/playlist?list=PLhMnuBfGeCDNgVzLPxF9o5UNKG1b-LFY9",children:(0,n.jsx)(A.img,{alt:"UC Berkeley CS 61A The Structure and Interpretation of Computer Programs, Spring 2010",src:s(4373).A+"",width:"320",height:"240"})})}),"\n",(0,n.jsx)(A.h2,{id:"lisp-macros",children:"Lisp Macros"}),"\n",(0,n.jsx)(A.p,{children:"If you want to learn more about lisp macros, there are two great books:"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.a,{href:"https://www.paulgraham.com/onlisp.html",children:"On Lisp"})," by ",(0,n.jsx)(A.a,{href:"https://www.paulgraham.com",children:"Paul Graham"})]}),"\n",(0,n.jsx)(A.p,{children:"The book is out of print, and you can download it for free. But if you prefer printed books, you\ncan get it printed on Lulu Express."}),"\n",(0,n.jsx)(A.p,{children:"Here is article that explain how to do this:"}),"\n"]}),"\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.lurklurk.org/onlisp/onlisp.html",children:'Piecing Together a Printed Copy of "On Lisp"'})}),"\n",(0,n.jsxs)(A.p,{children:["You can also read this ",(0,n.jsx)(A.a,{href:"https://www.reddit.com/r/lisp/comments/l71amc/on_lisp_paperback_replica/",children:"discussion on\nReddit"}),"."]}),"\n"]}),"\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsxs)(A.p,{children:["Another great book about advanced lisp macros is ",(0,n.jsx)(A.a,{href:"https://letoverlambda.com/",children:"Let over Lambda"})," by\n",(0,n.jsx)(A.a,{href:"https://hoytech.com/",children:"Doug Hoyte"}),"."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(A.h2,{id:"scheme-hygienic-macros",children:"Scheme hygienic macros"}),"\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.strong,{children:"NOTE"}),": Unfortunately, there are no good books about Scheme hygienic macros. But you can read\nthose documents:"]}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://github.com/mnieper/scheme-macros",children:"Writing Powerful Macros in Scheme"})," by ",(0,n.jsx)(A.a,{href:"https://github.com/mnieper",children:"Marc\nNieper-Wi\xdfkirchen"}),"."]}),"\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"http://www.phyast.pitt.edu/~micheles/syntax-rules.pdf",children:"JRM\u2019s Syntax-rules Primer for the Merely Eccentric"})}),"\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://www.eighty-twenty.org/~tonyg/Darcs/macromod/doc/reference/petrofsky/petrofsky-advanced-syntax-rules-primer-for-the-mildly-insane.txt",children:"An Advanced Syntax-Rules Primer for the Mildly Insane"})," by Al Petrofsky."]}),"\n",(0,n.jsxs)(A.li,{children:["Oleg Kiselyov part of the website contains ",(0,n.jsx)(A.a,{href:"https://okmij.org/ftp/Scheme/macros.html",children:"advanced usage of Scheme maros"}),"."]}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:"You can also find additional resources in these Reddit posts:"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"https://www.reddit.com/r/scheme/comments/3chowf/collection_of_links_about_scheme_macros/",children:"Collection of Links About Scheme Macros"})}),"\n"]}),"\n",(0,n.jsx)(A.h2,{id:"more-resources",children:"More Resources"}),"\n",(0,n.jsxs)(A.p,{children:["You can find common recipes inside ",(0,n.jsx)(A.a,{href:"https://cookbook.scheme.org/",children:"Scheme Cookbook"})," and ",(0,n.jsx)(A.a,{href:"https://books.scheme.org/",children:"more books\nabout Scheme"})," on ",(0,n.jsx)(A.a,{href:"https://www.scheme.org/",children:"official Scheme website"}),"."]})]})}function a(e={}){const{wrapper:A}={...(0,t.R)(),...e.components};return A?(0,n.jsx)(A,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},4373:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SCIP-lectures-berkley-9dcb64a06d3ce6ec281dc003f894e6c5.jpg"},2938:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SICP-cover-5b2540e90b3fe95223bfb2c4aea5c160.jpg"},234:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SICP-lectures-ce39601d03e68eb5ee40bced0737452f.jpg"},8446:(e,A,s)=>{s.d(A,{A:()=>r});const r="data:image/png;base64,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"},8453:(e,A,s)=>{s.d(A,{R:()=>c,x:()=>o});var r=s(6540);const n={},t=r.createContext(n);function c(e){const A=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(A):{...A,...e}}),[A,e])}function o(e){let A;return A=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),r.createElement(t.Provider,{value:A},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/840797c7.c96b5ad6.js b/assets/js/840797c7.c96b5ad6.js deleted file mode 100644 index 8144ab62..00000000 --- a/assets/js/840797c7.c96b5ad6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[478],{3055:(e,A,s)=>{s.r(A),s.d(A,{assets:()=>i,contentTitle:()=>o,default:()=>a,frontMatter:()=>c,metadata:()=>r,toc:()=>h});const r=JSON.parse('{"id":"scheme-intro/next-step","title":"What Next?","description":"Few resources how to learn more about Scheme","source":"@site/docs/scheme-intro/next-step.md","sourceDirName":"scheme-intro","slug":"/scheme-intro/next-step","permalink":"/docs/scheme-intro/next-step","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/scheme-intro/next-step.md","tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"sidebar_position":8,"description":"Few resources how to learn more about Scheme"},"sidebar":"tutorialSidebar","previous":{"title":"Continuations","permalink":"/docs/scheme-intro/continuations"},"next":{"title":"LIPS introduction","permalink":"/docs/category/lips-introduction"}}');var n=s(4848),t=s(8453);const c={sidebar_position:8,description:"Few resources how to learn more about Scheme"},o="What Next?",i={},h=[{value:"Scheme",id:"scheme",level:2},{value:"Lisp Macros",id:"lisp-macros",level:2},{value:"Scheme hygienic macros",id:"scheme-hygienic-macros",level:2},{value:"More Resources",id:"more-resources",level:2}];function l(e){const A={a:"a",h1:"h1",h2:"h2",header:"header",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(A.header,{children:(0,n.jsx)(A.h1,{id:"what-next",children:"What Next?"})}),"\n",(0,n.jsx)(A.p,{children:"If you want to learn more about Scheme, here are some recommended resources:"}),"\n",(0,n.jsx)(A.h2,{id:"scheme",children:"Scheme"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://www.t3x.org/sketchy/",children:"Sketchy Scheme"})," by ",(0,n.jsx)(A.a,{href:"https://www.t3x.org/",children:"Nils M Holm"})]}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.img,{alt:"Sketchy Scheme Book Cover",src:s(8446).A+"",width:"417",height:"621"})}),"\n",(0,n.jsxs)(A.p,{children:["There is a free version in Archive.org called ",(0,n.jsx)(A.a,{href:"https://archive.org/details/sketchy-lisp",children:"Sketchy Lisp"})," but I recommend latest version."]}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"https://web.mit.edu/6.001/6.037/sicp.pdf",children:"Structure and Interpretation of Computer Programs"})}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:"A classic, one of the authors of the book is the author of Scheme language."}),"\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.img,{alt:"SICP Cover",src:s(2938).A+"",width:"400",height:"579"}),(0,n.jsx)("br",{}),"\n",(0,n.jsxs)("small",{children:[(0,n.jsx)("a",{href:"https://commons.wikimedia.org/wiki/File:SICP_cover.jpg",children:"Harold Abelson and Gerald Jay Sussman with Julie Sussman\xa0\u2014\xa0MIT Press"}),", ",(0,n.jsx)("a",{href:"https://creativecommons.org/licenses/by-sa/4.0",children:"CC BY-SA 4.0"}),", Wikimedia Commons"]})]}),"\n",(0,n.jsx)(A.p,{children:"I also recommend video lectures. There are two versions. I recommend original by Abelson and Sussman from 1986."}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.youtube.com/playlist?list=PLB63C06FAF154F047",children:(0,n.jsx)(A.img,{alt:"SICP MIT Lectures",src:s(234).A+"",width:"320",height:"240"})})}),"\n",(0,n.jsxs)(A.p,{children:["Here is the ",(0,n.jsx)(A.a,{href:"https://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/",children:"official website of the lectures"}),"."]}),"\n",(0,n.jsx)(A.p,{children:"They are not very good quality, but they are great, and you should have no problems in seeing the\ncode on the blackboard."}),"\n",(0,n.jsxs)(A.p,{children:["There are also more recent lectures from 2010 at ",(0,n.jsx)(A.a,{href:"https://www.berkeley.edu/",children:"Berkeley"})," by\n",(0,n.jsx)(A.a,{href:"https://people.eecs.berkeley.edu/~bh/",children:"Brian Harvey"}),". Only a little bit better quality."]}),"\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.youtube.com/playlist?list=PLhMnuBfGeCDNgVzLPxF9o5UNKG1b-LFY9",children:(0,n.jsx)(A.img,{alt:"UC Berkeley CS 61A The Structure and Interpretation of Computer Programs, Spring 2010",src:s(4373).A+"",width:"320",height:"240"})})}),"\n",(0,n.jsx)(A.h2,{id:"lisp-macros",children:"Lisp Macros"}),"\n",(0,n.jsx)(A.p,{children:"If you want to learn more about lisp macros, there are two great books:"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.a,{href:"https://www.paulgraham.com/onlisp.html",children:"On Lisp"})," by ",(0,n.jsx)(A.a,{href:"https://www.paulgraham.com",children:"Paul Graham"})]}),"\n",(0,n.jsx)(A.p,{children:"The book is out of print, and you can download it for free. But if you prefer printed books, you\ncan get it printed on Lulu Express."}),"\n",(0,n.jsx)(A.p,{children:"Here is article that explain how to do this:"}),"\n"]}),"\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsx)(A.p,{children:(0,n.jsx)(A.a,{href:"https://www.lurklurk.org/onlisp/onlisp.html",children:'Piecing Together a Printed Copy of "On Lisp"'})}),"\n",(0,n.jsxs)(A.p,{children:["You can also read this ",(0,n.jsx)(A.a,{href:"https://www.reddit.com/r/lisp/comments/l71amc/on_lisp_paperback_replica/",children:"discussion on\nReddit"}),"."]}),"\n"]}),"\n",(0,n.jsxs)(A.li,{children:["\n",(0,n.jsxs)(A.p,{children:["Another great book about advanced lisp macros is ",(0,n.jsx)(A.a,{href:"https://letoverlambda.com/",children:"Let over Lambda"})," by\n",(0,n.jsx)(A.a,{href:"https://hoytech.com/",children:"Doug Hoyte"}),"."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(A.h2,{id:"scheme-hygienic-macros",children:"Scheme hygienic macros"}),"\n",(0,n.jsxs)(A.p,{children:[(0,n.jsx)(A.strong,{children:"NOTE"}),": Unfortunately, there are no good books about Scheme hygienic macros. But you can read\nthose documents:"]}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://github.com/mnieper/scheme-macros",children:"Writing Powerful Macros in Scheme"})," by ",(0,n.jsx)(A.a,{href:"https://github.com/mnieper",children:"Marc\nNieper-Wi\xdfkirchen"}),"."]}),"\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"http://www.phyast.pitt.edu/~micheles/syntax-rules.pdf",children:"JRM\u2019s Syntax-rules Primer for the Merely Eccentric"})}),"\n",(0,n.jsxs)(A.li,{children:[(0,n.jsx)(A.a,{href:"https://www.eighty-twenty.org/~tonyg/Darcs/macromod/doc/reference/petrofsky/petrofsky-advanced-syntax-rules-primer-for-the-mildly-insane.txt",children:"An Advanced Syntax-Rules Primer for the Mildly Insane"})," by Al Petrofsky."]}),"\n",(0,n.jsxs)(A.li,{children:["Oleg Kiselyov part of the website contains ",(0,n.jsx)(A.a,{href:"https://okmij.org/ftp/Scheme/macros.html",children:"advanced usage of Scheme maros"}),"."]}),"\n"]}),"\n",(0,n.jsx)(A.p,{children:"You can also find additional resources in these Reddit posts:"}),"\n",(0,n.jsxs)(A.ul,{children:["\n",(0,n.jsx)(A.li,{children:(0,n.jsx)(A.a,{href:"https://www.reddit.com/r/scheme/comments/3chowf/collection_of_links_about_scheme_macros/",children:"Collection of Links About Scheme Macros"})}),"\n"]}),"\n",(0,n.jsx)(A.h2,{id:"more-resources",children:"More Resources"}),"\n",(0,n.jsxs)(A.p,{children:["You can find common recipes inside ",(0,n.jsx)(A.a,{href:"https://cookbook.scheme.org/",children:"Scheme Cookbook"})," and ",(0,n.jsx)(A.a,{href:"https://books.scheme.org/",children:"more books\nabout Scheme"})," on ",(0,n.jsx)(A.a,{href:"https://www.scheme.org/",children:"official Scheme website"}),"."]})]})}function a(e={}){const{wrapper:A}={...(0,t.R)(),...e.components};return A?(0,n.jsx)(A,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},4373:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SCIP-lectures-berkley-9dcb64a06d3ce6ec281dc003f894e6c5.jpg"},2938:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SICP-cover-5b2540e90b3fe95223bfb2c4aea5c160.jpg"},234:(e,A,s)=>{s.d(A,{A:()=>r});const r=s.p+"assets/images/SICP-lectures-ce39601d03e68eb5ee40bced0737452f.jpg"},8446:(e,A,s)=>{s.d(A,{A:()=>r});const r="data:image/png;base64,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"},8453:(e,A,s)=>{s.d(A,{R:()=>c,x:()=>o});var r=s(6540);const n={},t=r.createContext(n);function c(e){const A=r.useContext(t);return r.useMemo((function(){return"function"==typeof e?e(A):{...A,...e}}),[A,e])}function o(e){let A;return A=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:c(e.components),r.createElement(t.Provider,{value:A},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e1902777.a8610025.js b/assets/js/e1902777.a8610025.js deleted file mode 100644 index 70f6a6a6..00000000 --- a/assets/js/e1902777.a8610025.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[8177],{4877:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"lips/intro","title":"Core features","description":"Core LIPS features added on top of Scheme, related to JavaScript","source":"@site/docs/lips/intro.md","sourceDirName":"lips","slug":"/lips/intro","permalink":"/docs/lips/intro","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/lips/intro.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"sidebar_position":1,"description":"Core LIPS features added on top of Scheme, related to JavaScript"},"sidebar":"tutorialSidebar","previous":{"title":"LIPS introduction","permalink":"/docs/category/lips-introduction"},"next":{"title":"Reflection","permalink":"/docs/lips/reflection"}}');var a=s(4848),i=s(8453);const t={sidebar_position:1,description:"Core LIPS features added on top of Scheme, related to JavaScript"},c="Core features",o={},l=[{value:"Special constants",id:"special-constants",level:2},{value:"Numerical tower",id:"numerical-tower",level:2},{value:"Print procedure",id:"print-procedure",level:2},{value:"Emoji",id:"emoji",level:2},{value:"Macros",id:"macros",level:2},{value:"Gensyms",id:"gensyms",level:3},{value:"Single argument eval",id:"single-argument-eval",level:2},{value:"Procedures",id:"procedures",level:2},{value:"length property",id:"length-property",level:3},{value:"Doc strings",id:"doc-strings",level:2},{value:"Typechecking",id:"typechecking",level:2},{value:"Integration with JavaScript",id:"integration-with-javascript",level:2},{value:"Dot notation",id:"dot-notation",level:3},{value:"Mutating object properties",id:"mutating-object-properties",level:3},{value:"Date and Time",id:"date-and-time",level:3},{value:"Interact with DOM",id:"interact-with-dom",level:3},{value:"Boxing",id:"boxing",level:3},{value:"Procedures",id:"procedures-1",level:3},{value:"Procedure arity",id:"procedure-arity",level:4},{value:"Helper macros and functions",id:"helper-macros-and-functions",level:3},{value:"Legacy macros and functions",id:"legacy-macros-and-functions",level:4},{value:"The dot operator",id:"the-dot-operator",level:5},{value:"The double dot operator",id:"the-double-dot-operator",level:5},{value:"Usage of Legacy .. and . operators",id:"usage-of-legacy--and--operators",level:5},{value:"Scheme functions",id:"scheme-functions",level:3},{value:"JavaScript functions",id:"javascript-functions",level:3},{value:"Callbacks",id:"callbacks",level:3},{value:"Regular Expressions",id:"regular-expressions",level:3},{value:"Vectors",id:"vectors",level:3},{value:"Object literals",id:"object-literals",level:3},{value:"Automagic async/await",id:"automagic-asyncawait",level:3},{value:"Promise quotation",id:"promise-quotation",level:3},{value:"Promises vs delay expression",id:"promises-vs-delay-expression",level:3},{value:"Exceptions",id:"exceptions",level:3},{value:"JavaScript Generars and iterators",id:"javascript-generars-and-iterators",level:3},{value:"Classes",id:"classes",level:3},{value:"Node.js",id:"nodejs",level:3},{value:"ES Modules",id:"es-modules",level:3},{value:"Finding LIPS Scheme directory",id:"finding-lips-scheme-directory",level:3},{value:"Binary compiler",id:"binary-compiler",level:2},{value:"loading SRFI",id:"loading-srfi",level:2},{value:"Limitations",id:"limitations",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"core-features",children:"Core features"})}),"\n",(0,a.jsx)(n.h2,{id:"special-constants",children:"Special constants"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define ",(0,a.jsx)(n.code,{children:"#null"})," and ",(0,a.jsx)(n.code,{children:"#void"})," as Parser constants so they can be used inside quoted expressions:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(#null #void)))\n (write (symbol? (car lst)))\n (newline)\n (write (symbol? (cadr lst)))\n (newline))\n;; ==> #f\n;; ==> #f\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," ",(0,a.jsx)(n.code,{children:"#null"})," is the same as JavaScript ",(0,a.jsx)(n.code,{children:"null"})," value and it's a false value. Similar to\n",(0,a.jsx)(n.a,{href:"https://www.gnu.org/software/kawa/index.html",children:"Kawa Scheme"})," that use ",(0,a.jsx)(n.code,{children:"#!null"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"#void"})," constants is the same as result of ",(0,a.jsx)(n.code,{children:"(value)"})," or ",(0,a.jsx)(n.code,{children:"(if #f #f)"}),". In Scheme it's unspecified value,\nbut in LIPS it's JavaScript undefined. ",(0,a.jsx)(n.code,{children:"#void"})," is not false value."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(eq? (if #f #f) (values))\n;; ==> #t\n"})}),"\n",(0,a.jsx)(n.h2,{id:"numerical-tower",children:"Numerical tower"}),"\n",(0,a.jsx)(n.p,{children:"LIPS support full numerical tower (not yet 100% unit tested):"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"integers - using BitInt"}),"\n",(0,a.jsx)(n.li,{children:"floats - using JavaScript numbers"}),"\n",(0,a.jsx)(n.li,{children:"rationals"}),"\n",(0,a.jsx)(n.li,{children:"complex numbers (that can use integers, floats, or rationals)"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"print-procedure",children:"Print procedure"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define helper ",(0,a.jsx)(n.code,{children:"print"})," procedure that display all its arguments with newline after each element."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(print 1 2 3)\n;; ==> 1\n;; ==> 2\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.h2,{id:"emoji",children:"Emoji"}),"\n",(0,a.jsx)(n.p,{children:"LIPS fully supports all Unicode characters, including emoji:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define smiley #\\\ud83d\ude00)\n(define poo #\\\ud83d\udca9)\n(write (string-append (string smiley) " " (string poo)))\n;; ==> "\ud83d\ude00 \ud83d\udca9"\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also use them as part of symbols (e.g. as variables name):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (\u23cf\ufe0f)\n (print "ejecting"))\n(\u23cf\ufe0f)\n;; ==> ejecting\n'})}),"\n",(0,a.jsx)(n.h2,{id:"macros",children:"Macros"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define both Lisp macros and Scheme hygienic macros (",(0,a.jsx)(n.code,{children:"syntax-rules"}),")."]}),"\n",(0,a.jsx)(n.p,{children:"It also implements:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-46/",children:"SRFI-46"})," which allows changing the ellipsis symbol for nested syntax-rules."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-139/",children:"SRFI-139"})," which allows defining\n",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#anaphoric-hygienic-macros",children:"anaphoric syntax-rules macros"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-147/",children:"SRFI-147"})," which allows defining a new syntax-rules macros to define syntax-rules macros."]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"gensyms",children:"Gensyms"}),"\n",(0,a.jsxs)(n.p,{children:["With lisp macros you can use ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#gensyms",children:"gensyms"}),", they are special Scheme\nsymbols that use JavaScript symbols behind the scene, so they are proven to be unique. Additionally\nyou can use named gensym if you pass string as first argument:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(gensym)\n;; ==> #:g5\n(gensym "sym")\n;; ==> #:sym\n'})}),"\n",(0,a.jsx)(n.h2,{id:"single-argument-eval",children:"Single argument eval"}),"\n",(0,a.jsxs)(n.p,{children:["Eval in LIPS don't require second argument to ",(0,a.jsx)(n.code,{children:"eval"}),". The environment is optional and default\nit's a result of calling ",(0,a.jsx)(n.code,{children:"(interaction-environment)"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(eval '(+ x x))\n;; ==> 20\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(let ((x 20))\n (eval '(- x)))\n;; ==> -10\n"})}),"\n",(0,a.jsx)(n.p,{children:"But you can also use the second arguments:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(let ((x 20))\n (eval '(- x) (current-environment)))\n;; ==> -20\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Read more about ",(0,a.jsx)(n.a,{href:"/docs/lips/environments",children:"LIPS environments"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"procedures",children:"Procedures"}),"\n",(0,a.jsxs)(n.p,{children:["Procedures in LIPS have access additional objects ",(0,a.jsx)(n.code,{children:"arguments"}),", but the have nothing to do with JavaScript.\narguments is an array/vector with calling arguments and it have an object callee which points to the same\nprocedure. So you can create recursive functions with anonymous lambda:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"((lambda (n)\n (if (<= n 0)\n 1\n (* n (arguments.callee (- n 1))))) 10)\n;; ==> 3628800\n"})}),"\n",(0,a.jsx)(n.p,{children:"This is classic factorial function written as lambda without the name."}),"\n",(0,a.jsx)(n.h3,{id:"length-property",children:"length property"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS functions similarly to JavaScript functions also have ",(0,a.jsx)(n.code,{children:"length"})," property that indicate how many\narguments a function accepts. If function get more or less argumenets it's not an error like in Scheme. More arguments are ignored,\nand if less arguments are passed they are ",(0,a.jsx)(n.code,{children:"undefined"})," (",(0,a.jsx)(n.code,{children:"#void"}),")."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b c)\n (+ a b c))\n\n(print sum.length)\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.p,{children:"It return number of number arguments the rest (dot notation) arguments are ignored."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b . rest)\n (apply + a b rest))\n\n(print sum.length)\n;; ==> 3\n(sum 1 2 3 4 5 6)\n;; ==> 21\n"})}),"\n",(0,a.jsx)(n.h2,{id:"doc-strings",children:"Doc strings"}),"\n",(0,a.jsx)(n.p,{children:"Procedures, macros, and variables can have doc strings."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (factorial n)\n "(factorial n)\n\n Calculate factorial of a given number"\n (if (<= n 0)\n 1\n (* n (factorial (- n 1)))))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can access doc string with ",(0,a.jsx)(n.code,{children:"help"})," procedure or with ",(0,a.jsx)(n.code,{children:"__doc__"})," property."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(write factorial.__doc__)\n"(factorial n)\n\nCalculate factorial of a given number"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["If you define variable or hygienic macro with doc string, the string is hidden (you can access it with ",(0,a.jsx)(n.code,{children:"__doc__"}),"),\nso help is the only way to access it:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-syntax q\n (syntax-rules ()\n ((_ x) \'x))\n "(q expression)\n\n Macro quote the expression")\n\n(write q.__doc__)\n;; ==> #void\n(help q)\n;; ==> (q expression)\n;; ==>\n;; ==> Macro quote the expression\n'})}),"\n",(0,a.jsx)(n.h2,{id:"typechecking",children:"Typechecking"}),"\n",(0,a.jsx)(n.p,{children:"LIPS do typechecking for all scheme procedures."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(+ "hello" 10)\n;; ==> Expecting number got string\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can incorporate typechecking in your own code:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((x 10))\n (typecheck "let" x "string" 0))\n;; ==> Expecting string got number in expression `let` (argument 0)\n(let ((x "string"))\n (typecheck "let" x "number"))\n;; ==> Expecting number got string in expression `let`\n'})}),"\n",(0,a.jsx)(n.p,{children:"There is also another function to check type of number:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((i 10+10i))\n (typecheck-number "let" i "bigint"))\n;; ==> Expecting bigint got complex in expression `let`\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": In LIPS all integers are BigInts."]}),"\n",(0,a.jsxs)(n.p,{children:["The last typecking function is ",(0,a.jsx)(n.code,{children:"typecheck-args"})," that check if all arguments are of same type."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((number \'(1 10 1/2 10+10i)))\n (typecheck-args "number" "let" number))\n;; ==> #void\n(let ((number \'(1 10 1/2 "string")))\n (typecheck-args "number" "let" number))\n;; ==> Expecting number got string in expression `let` (argument 4)\n'})}),"\n",(0,a.jsx)(n.h2,{id:"integration-with-javascript",children:"Integration with JavaScript"}),"\n",(0,a.jsx)(n.h3,{id:"dot-notation",children:"Dot notation"}),"\n",(0,a.jsx)(n.p,{children:"LIPS allow accessing JavaScript objects with dot notation:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"document.querySelector\n;; ==> #\n"})}),"\n",(0,a.jsx)(n.h3,{id:"mutating-object-properties",children:"Mutating object properties"}),"\n",(0,a.jsxs)(n.p,{children:["You can use dot notation with ",(0,a.jsx)(n.code,{children:"set!"})," to change the value:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(set! self.foo 10)\nself.foo\n"})}),"\n",(0,a.jsxs)(n.p,{children:["top level ",(0,a.jsx)(n.code,{children:"self"})," always points to a global object ",(0,a.jsx)(n.code,{children:"window"})," in browser or ",(0,a.jsx)(n.code,{children:"global"})," in Node."]}),"\n",(0,a.jsxs)(n.p,{children:["There is also older API that still work, which is ",(0,a.jsx)(n.code,{children:"set-obj!"})," but with dot notation you don't\nneed it anymore:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(set-obj! self 'foo 10)\n(display self.foo)\n;; ==> 10\n"})}),"\n",(0,a.jsx)(n.p,{children:"In both platforms you can access global JavaScript objects like normal variables:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! self.greet "hello, LIPS")\n(write greet)\n;; ==> "hello, LIPS"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"date-and-time",children:"Date and Time"}),"\n",(0,a.jsxs)(n.p,{children:["Since we have full access to JavaScript, we can access the ",(0,a.jsx)(n.code,{children:"Date"})," object to manipulate date and time."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (new Date "2024-01-01 12:09:2")\n (getFullYear))\n;; ==> 2024\n'})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (format-part number)\n "(format-part number)\n\n Convert number to string with leading zero. It should be used\n for minutes, hours, and seconds."\n (--\x3e number (toString) (padStart 2 "0")))\n\n(let ((date (new Date "2024-01-01 12:09:02")))\n (format "~a:~a:~a"\n (format-part (date.getHours))\n (format-part (date.getMinutes))\n (format-part (date.getSeconds))))\n;; ==> "12:09:02"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also use Date time libraries like ",(0,a.jsx)(n.a,{href:"https://date-fns.org/",children:"date-fns"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"interact-with-dom",children:"Interact with DOM"}),"\n",(0,a.jsxs)(n.p,{children:["Here is example how to add button to the page and add onclick handler using browser DOM\n(",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model",children:"Document Object Model"}),") API."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((button (document.createElement "button")))\n (set! button.innerHTML "click me!")\n (set! button.onclick (lambda () (alert "Hello, LIPS Scheme!")))\n (let ((style button.style))\n (set! style.position "absolute")\n (set! style.zIndex 9999)\n (set! style.top 0)\n (set! style.left 0))\n (document.body.appendChild button))\n'})}),"\n",(0,a.jsx)(n.h3,{id:"boxing",children:"Boxing"}),"\n",(0,a.jsx)(n.p,{children:"LIPS have its own representation for numbers, strings and characters. And when\ninteracting with JavaScript the values may get boxed or unboxed automagically."}),"\n",(0,a.jsxs)(n.p,{children:["You should not confuse boxing with boxes (",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-111/",children:"SRFI-111"})," and\n",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-195",children:"SRFI-195"}),"). LIPS boxing are part of implementation of Scheme\ndata types. And SRFI boxes are containers written in Scheme. Name boxing came from JavaScript, when\nprimitive values are wrapped in objects when you try to use them in object context (like accessing\na property)."]}),"\n",(0,a.jsx)(n.p,{children:"You need to be careful with some of the JavaScript native methods, since they can unbox the value when you don't\nwhen them to be unboxed."}),"\n",(0,a.jsxs)(n.p,{children:["Example is ",(0,a.jsx)(n.code,{children:"Array::push"})," using with native LIPS types:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((v (vector)))\n (v.push 1/2)\n (print v))\n;; ==> #(0.5)\n"})}),"\n",(0,a.jsx)(n.p,{children:"As you can see the rational number got unboxed and converted into JavaScript float numbers.\nUnboxing always can make you loose some information because LIPS types needs to be converted into native JavaScript\ndata types. And JavaScript doesn't have a notion of rationals, there are only floating point numbers, and big ints."}),"\n",(0,a.jsx)(n.h3,{id:"procedures-1",children:"Procedures"}),"\n",(0,a.jsx)(n.p,{children:"LIPS Scheme procedures are JavaScript functions, so you can call them from JavaScript."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! self.greet (lambda () "hello, LIPS"))\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can call this function from JavaScript"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"console.log(greet());\n// ==> {__string__: 'hello, LIPS'}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Note that the value was not automagically unboxed because we are no longer in LIPS Scheme code and LIPS can't access native\nJavaScript. So to get the real a string you need to call ",(0,a.jsx)(n.code,{children:"valueoOf()"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"console.log(greet().valueOf());\n// ==> hello, LIPS\n"})}),"\n",(0,a.jsx)(n.h4,{id:"procedure-arity",children:"Procedure arity"}),"\n",(0,a.jsx)(n.p,{children:"LIPS don't check the number of argumnents when calling a procedure:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((test (lambda (a b c)\n (print a b c))))\n (test 10))\n;; ==> 10\n;; ==> #void\n;; ==> #void\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The same as with JavaScript if you don't pass an argument it will be undefined. But you still have full compatible with Scheme and use ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#variable-number-of-arguments",children:"arguments with variable artity"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((test (lambda (first . rest)\n (apply print first rest))))\n (test 1)\n (test 2 3 4))\n;; ==> 1\n;; ==> 2\n;; ==> 3\n;; ==> 4\n"})}),"\n",(0,a.jsx)(n.h3,{id:"helper-macros-and-functions",children:"Helper macros and functions"}),"\n",(0,a.jsxs)(n.p,{children:["The most useful macro in LIPS (for interacting with JavaScript) is ",(0,a.jsx)(n.code,{children:"--\x3e"})," it acts like a chain of\nmethod calls in JavaScript"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e "this is string" (split " ") (reverse) (join " "))\n;; ==> "string is this"\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can chain methods that return arrays or string and call a method of them. The above expression\nis the same as JavaScript:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"\"this is string\".split(' ').reverse().join(' ');\n"})}),"\n",(0,a.jsx)(n.p,{children:"With --\x3e you can also gab property of a function:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #/x/ (test.call #/foo/ "foo"))\n;; ==> #t\n(let ((test-bar (--\x3e #/x/ (test.bind #/bar/i))))\n (test-bar "BAR"))\n;; ==> #t\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also return a function:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define test (--\x3e #/x/ test))\n(test.call #/foo/ "foo")\n;; ==> #t\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Read more about ",(0,a.jsx)(n.a,{href:"https://tinyurl.com/ykvb836s",children:"function::bind"})," and\n",(0,a.jsx)(n.a,{href:"https://tinyurl.com/yc6j7fdh",children:"function::call"})," on ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/",children:"MDN"}),"."]}),"\n",(0,a.jsx)(n.h4,{id:"legacy-macros-and-functions",children:"Legacy macros and functions"}),"\n",(0,a.jsx)(n.p,{children:"There are two legacy macros that are still part of LIPS, but you don't need\nthem most of the time."}),"\n",(0,a.jsx)(n.h5,{id:"the-dot-operator",children:"The dot operator"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"."})," - dot function was a first way to interact with JavaScript, it allowed to get property from an\nobject:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(. document 'querySelector)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["This returned function querySelector from document object in browser. Note that dot a function can only appear\nas first element of the list (it's handled in special way by the parser). In any other place dot is a pair separator,\nsee documentation about ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/data-types#pairs",children:"Pairs in Scheme"}),"."]}),"\n",(0,a.jsx)(n.h5,{id:"the-double-dot-operator",children:"The double dot operator"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:".."})," - this is a macro is that simplify usage of ",(0,a.jsx)(n.code,{children:"."})," procedure:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(.. document.querySelector)\n"})}),"\n",(0,a.jsxs)(n.h5,{id:"usage-of-legacy--and--operators",children:["Usage of Legacy ",(0,a.jsx)(n.code,{children:".."})," and ",(0,a.jsx)(n.code,{children:"."})," operators"]}),"\n",(0,a.jsxs)(n.p,{children:["You still sometimes may want to use ",(0,a.jsx)(n.code,{children:"."})," instead of ",(0,a.jsx)(n.code,{children:"--\x3e"})," when you want to get\nproperty from an object returned by expression."]}),"\n",(0,a.jsx)(n.p,{children:"In the old version of LIPS, you have to execute code like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'((. document \'querySelector) "body")\n((.. document.querySelector) "body")\n'})}),"\n",(0,a.jsx)(n.p,{children:"The first expression return a Native JavaScript procedure that is then executed."}),"\n",(0,a.jsx)(n.p,{children:"This is equivalent of:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(document.querySelector "body")\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," the only time when you still need ",(0,a.jsx)(n.code,{children:"."})," function is when you want to get the property of\nobject returned by expression."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((style (. (document.querySelector "body") \'style)))\n (set! style.background "red"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Here we get a ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style",children:"style object"}),"\nfrom ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement",children:"the DOM node"})," without sorting the\nreference to the DOM node."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," because dot notation in symbols is not special syntax you can use code like this:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((x #(1 2 3)))\n (print x.0)\n (print x.1)\n (print x.2))\n;; ==> 1\n;; ==> 2\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.h3,{id:"scheme-functions",children:"Scheme functions"}),"\n",(0,a.jsx)(n.p,{children:"Scheme functions (lambda's) are JavaScript functions, so you can call them from JavaScript."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! window.foo (lambda () (alert "hello")))\n'})}),"\n",(0,a.jsx)(n.p,{children:"If you define function like this, in browser REPL, you can call it from JavaScript\n(e.g. browser developer console)."}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"TODO"})," Screenshot"]}),"\n",(0,a.jsx)(n.h3,{id:"javascript-functions",children:"JavaScript functions"}),"\n",(0,a.jsx)(n.p,{children:"You can call JavaScript functions from Scheme, the same as you call Scheme procedures:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(document.querySelector "body")\n;; ==> #\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In both browser and Node.js you can execute ",(0,a.jsx)(n.code,{children:"console.log"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(console.log "hello, LIPS")\n;; ==> hello, LIPS\n'})}),"\n",(0,a.jsx)(n.h3,{id:"callbacks",children:"Callbacks"}),"\n",(0,a.jsx)(n.p,{children:"You can use Scheme functions as callbacks to JavaScript functions:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map string->number))\n;; ==> #(1 +nan.0 +nan.0)\n'})}),"\n",(0,a.jsx)(n.p,{children:"This is classic issue with functions that accept more than one argument. You have samilar issue\nin JavaScript:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'["1", "2", "3"].map(parseInt)\n// ==> [1, NaN, NaN]\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": the value are different becaseu in Shceme i"]}),"\n",(0,a.jsx)(n.p,{children:"To fix the issue you can\ndefine lambda with single argument:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map (lambda (str) (string->number str))))\n;; ==> #(1 2 3)\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also use one of functional helpers insprired by ",(0,a.jsx)(n.a,{href:"https://ramdajs.com/",children:"Ramda"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map (unary string->number)))\n;; ==> #(1 2 3)\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"unary"})," ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#higher-order-functions",children:"higher-order procedure"})," accept a single\nprocedure and return new procedure that accept only one argument."]}),"\n",(0,a.jsxs)(n.p,{children:["To read more check ",(0,a.jsx)(n.a,{href:"/docs/lips/functional-helpers",children:"Functional helpers"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"WARNING"})," be careful when using scheme callback functions inside JavaScript.\nSince some code may be ",(0,a.jsx)(n.code,{children:"async"})," and your code may break."]}),"\n",(0,a.jsx)(n.p,{children:"Example of procedures that are not wise to use are:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"Array::forEach"})," - this function accepts a callaback but because it doesn't return\nanything, LIPS can't automatically await the response, and your code may execute out of order."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"String::replace"})," - this function can accept optional callback and if ",(0,a.jsx)(n.code,{children:"lambda"})," is async\nyou will end up with ",(0,a.jsx)(n.code,{children:"[object Promise]"})," in output string. Any macro or function can return\na promise in LIPS, and if any of the expression inside a function return a Promise, the whole\nfunction return a Promise and become async. Here is example code that demonstrate the problem:"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e "foo bar" (replace "foo" (lambda () (Promise.resolve "xxx"))))\n"[object Promise] bar"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Instead of ",(0,a.jsx)(n.code,{children:"Array::replace"})," you should use LIPS Scheme ",(0,a.jsx)(n.code,{children:"replace"})," procedure that works with async ",(0,a.jsx)(n.code,{children:"lambda"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(replace #/[a-z]+/g (lambda ()\n (Promise.resolve "lips"))\n "foo bar")\n;; ==> "lips lips"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"regular-expressions",children:"Regular Expressions"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define regular expressions it uses native JavaScript regular expressions.\nAt first, the syntax looked like in JavaScript. It was problematic for the parser\nso you were not able to put space after ",(0,a.jsx)(n.code,{children:"/"})," to distinguish from divide procedure.\nLater, the syntax was renamed into form that start with hash ",(0,a.jsx)(n.code,{children:"#/[0-9]/"}),". The same\nsyntax is used by ",(0,a.jsx)(n.a,{href:"https://practical-scheme.net/gauche/man/gauche-refe/Regular-expressions.html",children:"Gauche"})," implementation. But LIPS supports more flags (same as JavaScript)."]}),"\n",(0,a.jsx)(n.h3,{id:"vectors",children:"Vectors"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS Scheme vectors are JavaScript arrays. So you can execute methods on them with ",(0,a.jsx)(n.code,{children:"--\x3e"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("one" "two" "three") (join ":"))\n;; ==> "one:two:three"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"object-literals",children:"Object literals"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS you can define object literals with ",(0,a.jsx)(n.code,{children:"&"}),"\n",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extension"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name "Jack" :age 22))\n(write obj)\n;; ==> &(:name "Jack" :age 22)\n(console.log obj)\n;; ==> { name: \'Jack\', age: 22 }\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can nest object literals and mix them with different object:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name "Jack" :hobbies #("swimming" "programming")))\n(write obj.hobbies)\n;; ==> #("swimming" "programming")\n(console.log obj)\n;; ==> { name: \'Jack\', hobbies: [ \'swiming\', \'programming\' ] }\n'})}),"\n",(0,a.jsx)(n.p,{children:"Object similar to Scheme vectors, are immutable, and everything inside is quoted automatically:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name Jack))\n(write obj)\n;; ==> &(:name "Jack")\n'})}),"\n",(0,a.jsx)(n.p,{children:"But to make it possible to share objects with JavaScript, native LIPS values are automatically unboxed.\nSo instead of symbol representation you get a JavaScript string."}),"\n",(0,a.jsx)(n.p,{children:"You can also use quasiquote with object literals:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define jack (let ((name "Jack")\n (age 22))\n `&(:name ,name :age ,age)))\n(write jack)\n;; ==> &(:name "Jack" :age 22)\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": because of the construction of ",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extensions"})," and\n",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/data-types#quasiquote",children:"quasiquote"}),", you can't splice a list inside object literals:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((args (list \':foo "lorem" \':bar "ipsum")))\n `&(,@args))\n;; ==> pair (unquote-splicing args) is not a symbol!\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The reason why this work like this is because, syntax extensions (",(0,a.jsx)(n.code,{children:"&"}),") runs at parse time and LIPS macros are runtime.\nThis may change in the future when ",(0,a.jsx)(n.a,{href:"https://github.com/jcubic/lips/issues/169",children:"expansion time will be implemented"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Objects also have longhand form with ",(0,a.jsx)(n.code,{children:"object"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((obj (object :name \'Jack)))\n (write obj))\n;; ==> &(:name "Jack")\n'})}),"\n",(0,a.jsx)(n.p,{children:"But note that object macro is async (return a Promise) so it may be problematic when used it\nwith native JavaScript code."}),"\n",(0,a.jsxs)(n.p,{children:["Using long form ",(0,a.jsx)(n.code,{children:"(object)"})," syntax you can use splicing with help of ",(0,a.jsx)(n.code,{children:"eval"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((args \'(:foo "lorem" :bar "ipsum")))\n (eval `(object ,@args)))\n;; ==> &(:foo "lorem" :bar "ipsum")\n'})}),"\n",(0,a.jsx)(n.p,{children:"The same you can use macros that will return LIPS Scheme code:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-macro (create-object . args)\n `(object ,@args))\n\n(create-object :foo "lorem" :bar "ipsum")\n;; ==> &(:foo "lorem" :bar "ipsum")\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": this example macro works the same ",(0,a.jsx)(n.code,{children:"object"})," is it's not that useful, but you can create\nmore complex code where you will be able to generate object literals with splicing."]}),"\n",(0,a.jsx)(n.p,{children:"Object literal also have shorthad notation:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj &(:x :y)))\n (write obj))\n;; ==> &(:x #void :y #void)\n"})}),"\n",(0,a.jsx)(n.p,{children:"It creates two writtable slots, the rest of the props are read only:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj &(:x :y)))\n (set! obj.x 10)\n (set! obj.y 20)\n (write obj))\n;; ==> &(:x 10 :y 20)\n\n(let ((obj &(:x :y)))\n (set! obj.z 20)\n (write obj))\n;; ==> Cannot add property z, object is not extensible\n\n(let ((obj &(:x :y :z 10)))\n (set! obj.z 20)\n (write obj))\n;; ==> Cannot assign to read only property 'z' of object '#'\n"})}),"\n",(0,a.jsx)(n.h3,{id:"automagic-asyncawait",children:"Automagic async/await"}),"\n",(0,a.jsx)(n.p,{children:"LIPS do automatic async/await so it waits for any promise before evaluating\nnext expression."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(Promise.resolve "xxx")\n;; ==> "xxx"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["This simplifies code when using promises, for instance using\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API",children:"fetch API"})," (AJAX)."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (fetch "https://scheme.org.pl/test/") (text) (match #/

([^>]+)<\\/h1>/) 1)\n;; ==> "Scheme is Super Fun"\n'})}),"\n",(0,a.jsx)(n.p,{children:"This is equivalent of JavaScript using async/await:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'cons res = await fetch("https://scheme.org.pl/test/");\nconst text = await res.text();\ntext.match(/

([^>]+)<\\/h1>/)[1];\n'})}),"\n",(0,a.jsx)(n.h3,{id:"promise-quotation",children:"Promise quotation"}),"\n",(0,a.jsxs)(n.p,{children:["Sometimes you need to process promises as values, for this LIPS support quotation\nof promises. You escape automagic async/await realm and get access to promise as value:\nto quote a promise you use ",(0,a.jsx)(n.code,{children:"'>"}),"\n",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extension"}),". To again get into\nautomatic async/await you can use ",(0,a.jsx)(n.code,{children:"(await)"})," procedure"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((promise (--\x3e \'>(fetch "https://scheme.org.pl/test/")\n (then (lambda (res)\n (res.text)))\n (then (lambda (text)\n (. (text.match #/

([^>]+)<\\/h1>/) 1))))))\n (print (await promise)))\n;; ==> Scheme is Super Fun\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," Inside ",(0,a.jsx)(n.code,{children:"then"})," lambda promises are still automagically resolved."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e \'>(Promise.resolve "hello")\n (then (lambda (value)\n (print (string-append value " " (Promise.resolve "LIPS"))))))\n;; ==> hello LIPS\n'})}),"\n",(0,a.jsx)(n.h3,{id:"promises-vs-delay-expression",children:"Promises vs delay expression"}),"\n",(0,a.jsxs)(n.p,{children:["Don't confuse JavaScript promises with ",(0,a.jsx)(n.code,{children:"delay"})," expressions. Their representation looks similar:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(delay 10)\n;; ==> #\n'>(Promise.resolve 10)\n;; ==> #\n"})}),"\n",(0,a.jsxs)(n.p,{children:["You can check if a value is a promise by quoting the expression and using ",(0,a.jsx)(n.code,{children:"promise?"})," predicate:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((a '>10)\n (b '>(Promise.resolve 10)))\n (print (promise? a))\n (print (promise? b)))\n;; ==> #f\n;; ==> #t\n"})}),"\n",(0,a.jsx)(n.h3,{id:"exceptions",children:"Exceptions"}),"\n",(0,a.jsx)(n.p,{children:"LIPS Scheme use javascript exception system. To throw an exception you use:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(throw "This is error")\n;; ==> Error: This is error\n'})}),"\n",(0,a.jsx)(n.p,{children:"or"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(raise (new Error "error"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"raise"})," procedure throw any object and ",(0,a.jsx)(n.code,{children:"throw"})," wraps the argument in ",(0,a.jsx)(n.code,{children:"new Error"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"You can catch exceptions with LIPS specific try..catch..finally:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (catch (e)\n (print (string-append "error " e.message " was caught"))))\n;; ==> error nasty was caught\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also have finally expression:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (catch (e)\n (print (string-append "error " e.message " was caught")))\n (finally\n (print "nothing happened")))\n;; ==> error nasty was caught\n;; ==> nothing happened\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also define ",(0,a.jsx)(n.code,{children:"finally"})," without ",(0,a.jsx)(n.code,{children:"catch"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (finally\n (print "after error")))\n;; ==> after error\n;; ==> nasty\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," the order of execution is not expected, but it may change in the future."]}),"\n",(0,a.jsxs)(n.p,{children:["LIPS also define R",(0,a.jsx)("sup",{children:"7"}),"RS guard ",(0,a.jsx)(n.code,{children:"procedure"})," that is just a macro that use try..catch behind the scene:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(guard (e ((list? e) (print (string-append "Error: " (car e)))))\n (raise \'("error")))\n;; ==> Error: error\n'})}),"\n",(0,a.jsx)(n.h3,{id:"javascript-generars-and-iterators",children:"JavaScript Generars and iterators"}),"\n",(0,a.jsxs)(n.p,{children:["Right now there is no way to define JavaScript generators inside LIPS. You can create iterator using\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols",children:"iteration prorocol"}),",\nBut to have yield keyword you need ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/continuations",children:"continuations"}),", they are part of the\nLIPS Roadmap."]}),"\n",(0,a.jsx)(n.p,{children:"Here is example of creating iterator in LIPS:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj (object))\n (max 5))\n (set-obj! obj Symbol.iterator\n (lambda ()\n (let ((i 0))\n `&(:next ,(lambda ()\n (set! i (+ i 1))\n (if (> i max)\n `&(:done #t)\n `&(:done #f :value ,(/ 1 i))))))))\n (print (iterator->array obj))\n (print (Array.from obj)))\n;; ==> #(1 1/2 1/3 1/4 1/5)\n;; ==> #(1 1/2 1/3 1/4 1/5)\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Array.from"})," can't be used for every possible case because it will unbox the values (and convert\nrational to float), here it doesn't happen because LIPS don't treat JavaScript iterators in any\nspecial way (it may change in the future). But ",(0,a.jsx)(n.code,{children:"Array.from"})," will convert the array of rationals to\nfloat if used on normal vector:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(Array.from #(1/2 1/3 1/4 1/5))\n;; ==> #(0.5 0.3333333333333333 0.25 0.2)\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": be careful when using iterator protocol because any function side Scheme can return a promise. If you would change\nquoted object literal ",(0,a.jsx)(n.code,{children:"`&()"})," with longhand ",(0,a.jsx)(n.code,{children:"object"})," you will get an error because ",(0,a.jsx)(n.code,{children:"object"})," is async."]}),"\n",(0,a.jsxs)(n.p,{children:["You can abstract the use of iteration protocol with a macro, but to have real ",(0,a.jsx)(n.code,{children:"yield"})," keyword like\nsyntax you need ",(0,a.jsx)(n.code,{children:"call/cc"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also define generators inside JavaScript using ",(0,a.jsx)(n.code,{children:"self.eval"})," (JavaScript global ",(0,a.jsx)(n.code,{children:"eval"}),"):"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define gen (self.eval "(async function* gen(time, ...args) {\n function delay(time) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n }\n for (let x of args) {\n await delay(time);\n yield x;\n }\n })"))\n\n(iterator->array (gen 100 1 2 3 4 5))\n;; ==> #(1 2 3 4 5)\n'})}),"\n",(0,a.jsx)(n.p,{children:"Here is example of async generator written in JavaScript."}),"\n",(0,a.jsx)(n.h3,{id:"classes",children:"Classes"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS, you can define JavaScript classes with ",(0,a.jsx)(n.code,{children:"define-class"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-class Person Object\n (constructor (lambda (self name)\n (set! self.name name)))\n (greet (lambda (self)\n (string-append "hello, " self.name))))\n\n(define jack (new Person "Jack"))\n(write jack)\n;; ==> #\n(jack.greet)\n;; ==> "hello, Jack"\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"define-class"})," is macro written in Scheme that uses\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes",children:"JavaScript prototypes"})," behind the scene."]}),"\n",(0,a.jsxs)(n.p,{children:["The class always need to have a base class (parent) or you need to use ",(0,a.jsx)(n.code,{children:"null"}),". Classes have explicit\n",(0,a.jsx)(n.code,{children:"self"})," as first argument (similar to Python) but ",(0,a.jsx)(n.code,{children:"this"})," also works inside functions:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! jack.run (lambda () (string-append "run, " this.name)))\n(jack.run)\n;; ==> "run, Jack"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["To create the new instance of a Class, you can use ",(0,a.jsx)(n.code,{children:"new"})," procedure."]}),"\n",(0,a.jsx)(n.p,{children:"You can also manipulate JavaScript prototypes directly:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(write Person.prototype)\n;; ==> #\n(set! Person.prototype.toString (lambda () (string-append "#")))\n(display (jack.toString))\n;; ==> #\n'})}),"\n",(0,a.jsxs)(n.p,{children:["By default toString is not used for representation of objects, but you add representation if you want.\nSee ",(0,a.jsx)(n.a,{href:"/docs/lips/extension#new-homoiconic-data-types",children:"Homoiconic data types"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"nodejs",children:"Node.js"}),"\n",(0,a.jsxs)(n.p,{children:["In Node.js, you can load JavaScript modules with ",(0,a.jsx)(n.code,{children:"require"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define fs (require "fs/promises"))\n(let ((fname "tmp.txt"))\n (fs.writeFile fname "hello LIPS")\n (write (fs.readFile fname "utf-8")))\n;; ==> "hello LIPS"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In above code, you can see example of ",(0,a.jsx)(n.a,{href:"#automagic-asyncawait",children:"automagic async/await"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["If you have to use callback based API in Node, use\n",(0,a.jsx)(n.a,{href:"https://nodejs.org/api/util.html#utilpromisifyoriginal",children:"promisify function"})," from Module util."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also use the ",(0,a.jsx)(n.code,{children:"Promise"})," constructor yourself:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define fs (require "fs"))\n\n(define-macro (async expr)\n (let ((resolve (gensym "resolve"))\n (reject (gensym "reject")))\n `(new Promise (lambda (,resolve ,reject)\n ,(append expr (list `(lambda (err data)\n ;; Node.js error is null when no error\n (if err\n (,reject err)\n (,resolve data)))))))))\n\n(let ((fname "tmp.txt"))\n (async (fs.writeFile fname "Hello, LIPS!"))\n (write (async (fs.readFile fname "utf-8"))))\n;; ==> "Hello, LIPS!"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In the above example, we import a regular callback based fs module and use the ",(0,a.jsx)(n.code,{children:"Promise"})," constructor\nabstracted away with a ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#lisp-macros",children:"lisp macro"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"es-modules",children:"ES Modules"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS Scheme runs in ES Module, but ",(0,a.jsx)(n.code,{children:"import"})," is reserved for experimental R7RS modules. If you want\nto import module that is ESM only. You need to access JavaScript dynamic import. But ",(0,a.jsx)(n.code,{children:"global.import"})," is not defined. If you want to define JavaScript dynamic import, you can use code:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define $:import (global.eval "(x) => import(x)"))\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can use this function like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'(--\x3e ($:import "fs/promises") (readFile "README.md" "utf8"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["But it will also work with ESM only module that can't be imported with ",(0,a.jsx)(n.code,{children:"require"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"finding-lips-scheme-directory",children:"Finding LIPS Scheme directory"}),"\n",(0,a.jsxs)(n.p,{children:["With help from ",(0,a.jsx)(n.code,{children:"(require.resolve)"})," you can get the path of the root directory of LIPS Scheme:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (require.resolve "@jcubic/lips") (replace #/dist\\/[^\\/]+$/ ""))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Node.js REPL load lips from Common.jS file and ",(0,a.jsx)(n.code,{children:"require.resolve"})," returns path to file\n",(0,a.jsx)(n.code,{children:"dist/lips.cjs"}),", by removing with with String::replace and regular expression you can the real path\nto the root of the LIPS Scheme."]}),"\n",(0,a.jsx)(n.h2,{id:"binary-compiler",children:"Binary compiler"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS Scheme have dumb binary compiler. The compiler is a way to compress the LIPS Scheme code and\ncreate binary file that is faster to load. Compiler is use to make bootstrapping faster. The binary\nfile use ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/CBOR",children:"CBOR"})," serialization format that is then compressed\nwith ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/LZJB",children:"LZJB"})," algorithm that is pretty fast. And it can still be\ncompress further with gzip by the HTTP server."]}),"\n",(0,a.jsxs)(n.p,{children:["To compile/compress a file you can use ",(0,a.jsx)(n.code,{children:"-c"})," flag when executing ",(0,a.jsx)(n.code,{children:"lips"})," executable."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"$ lips -c file.scm\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can then execute the code with:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"$ lips -c file.xcb\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Will create ",(0,a.jsx)(n.code,{children:"file.xcb"})," in same directory. For smaller files it make not have a difference when\nloading ",(0,a.jsx)(n.code,{children:".xcb"})," or ",(0,a.jsx)(n.code,{children:".scm"})," files."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": directives ",(0,a.jsx)(n.code,{children:"#!fold-case"})," and ",(0,a.jsx)(n.code,{children:"#!no-fold-case"})," work only inside the parser and they are\ntreated as comments, so you can't compile the code that have those directives."]}),"\n",(0,a.jsx)(n.h2,{id:"loading-srfi",children:"loading SRFI"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS, you can use ",(0,a.jsx)(n.code,{children:"(load)"})," with path absolute or relative to the directory of the executed LIPS\nfile. But you can use special syntax that indicate the root directory of the LIPS Scheme."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(load "@lips/lib/srfi/1.scm")\n'})}),"\n",(0,a.jsxs)(n.p,{children:["This will load the code from ",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-1/srfi-1.html",children:"SRFI-1"})," List\nLibrary. You can use this syntax in Node based REPL (NPM executable). The same syntax should work\nwith the web. But note that the root directory reply on the path of the LIPS Scheme script file. So\nyou if you bundle the code with Webpack or Rollup, LIPS may not find the root URL and may not be\nable to load the proper file."]}),"\n",(0,a.jsx)(n.h2,{id:"limitations",children:"Limitations"}),"\n",(0,a.jsxs)(n.p,{children:["LISP Scheme currently don't support ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/continuations",children:"continuations"})," and ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#tail-call-optimization",children:"Tail Call\nOptimization"}),". But they are part of the roadmap for\nversion 1.0."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var r=s(6540);const a={},i=r.createContext(a);function t(e){const n=r.useContext(i);return r.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(a):e.components||a:t(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e1902777.fcbe341c.js b/assets/js/e1902777.fcbe341c.js new file mode 100644 index 00000000..65027740 --- /dev/null +++ b/assets/js/e1902777.fcbe341c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknew_docs=self.webpackChunknew_docs||[]).push([[8177],{4877:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>l});const r=JSON.parse('{"id":"lips/intro","title":"Core features","description":"Core LIPS features added on top of Scheme, related to JavaScript","source":"@site/docs/lips/intro.md","sourceDirName":"lips","slug":"/lips/intro","permalink":"/docs/lips/intro","draft":false,"unlisted":false,"editUrl":"https://github.com/LIPS-scheme/lips/tree/master/docs/docs/lips/intro.md","tags":[],"version":"current","sidebarPosition":1,"frontMatter":{"sidebar_position":1,"description":"Core LIPS features added on top of Scheme, related to JavaScript"},"sidebar":"tutorialSidebar","previous":{"title":"LIPS Documentation","permalink":"/docs/category/lips-introduction"},"next":{"title":"Reflection","permalink":"/docs/lips/reflection"}}');var a=s(4848),i=s(8453);const t={sidebar_position:1,description:"Core LIPS features added on top of Scheme, related to JavaScript"},c="Core features",o={},l=[{value:"Special constants",id:"special-constants",level:2},{value:"Numerical tower",id:"numerical-tower",level:2},{value:"Print procedure",id:"print-procedure",level:2},{value:"Emoji",id:"emoji",level:2},{value:"Macros",id:"macros",level:2},{value:"Gensyms",id:"gensyms",level:3},{value:"Single argument eval",id:"single-argument-eval",level:2},{value:"Procedures",id:"procedures",level:2},{value:"length property",id:"length-property",level:3},{value:"Doc strings",id:"doc-strings",level:2},{value:"Typechecking",id:"typechecking",level:2},{value:"Integration with JavaScript",id:"integration-with-javascript",level:2},{value:"Dot notation",id:"dot-notation",level:3},{value:"Mutating object properties",id:"mutating-object-properties",level:3},{value:"Date and Time",id:"date-and-time",level:3},{value:"Interact with DOM",id:"interact-with-dom",level:3},{value:"Boxing",id:"boxing",level:3},{value:"Procedures",id:"procedures-1",level:3},{value:"Procedure arity",id:"procedure-arity",level:4},{value:"Helper macros and functions",id:"helper-macros-and-functions",level:3},{value:"Legacy macros and functions",id:"legacy-macros-and-functions",level:4},{value:"The dot operator",id:"the-dot-operator",level:5},{value:"The double dot operator",id:"the-double-dot-operator",level:5},{value:"Usage of Legacy .. and . operators",id:"usage-of-legacy--and--operators",level:5},{value:"Scheme functions",id:"scheme-functions",level:3},{value:"JavaScript functions",id:"javascript-functions",level:3},{value:"Callbacks",id:"callbacks",level:3},{value:"Regular Expressions",id:"regular-expressions",level:3},{value:"Vectors",id:"vectors",level:3},{value:"Object literals",id:"object-literals",level:3},{value:"Automagic async/await",id:"automagic-asyncawait",level:3},{value:"Promise quotation",id:"promise-quotation",level:3},{value:"Promises vs delay expression",id:"promises-vs-delay-expression",level:3},{value:"Exceptions",id:"exceptions",level:3},{value:"JavaScript Generars and iterators",id:"javascript-generars-and-iterators",level:3},{value:"Classes",id:"classes",level:3},{value:"Node.js",id:"nodejs",level:3},{value:"ES Modules",id:"es-modules",level:3},{value:"Finding LIPS Scheme directory",id:"finding-lips-scheme-directory",level:3},{value:"Binary compiler",id:"binary-compiler",level:2},{value:"loading SRFI",id:"loading-srfi",level:2},{value:"Limitations",id:"limitations",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"core-features",children:"Core features"})}),"\n",(0,a.jsx)(n.h2,{id:"special-constants",children:"Special constants"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define ",(0,a.jsx)(n.code,{children:"#null"})," and ",(0,a.jsx)(n.code,{children:"#void"})," as Parser constants so they can be used inside quoted expressions:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((lst '(#null #void)))\n (write (symbol? (car lst)))\n (newline)\n (write (symbol? (cadr lst)))\n (newline))\n;; ==> #f\n;; ==> #f\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," ",(0,a.jsx)(n.code,{children:"#null"})," is the same as JavaScript ",(0,a.jsx)(n.code,{children:"null"})," value and it's a false value. Similar to\n",(0,a.jsx)(n.a,{href:"https://www.gnu.org/software/kawa/index.html",children:"Kawa Scheme"})," that use ",(0,a.jsx)(n.code,{children:"#!null"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"#void"})," constants is the same as result of ",(0,a.jsx)(n.code,{children:"(value)"})," or ",(0,a.jsx)(n.code,{children:"(if #f #f)"}),". In Scheme it's unspecified value,\nbut in LIPS it's JavaScript undefined. ",(0,a.jsx)(n.code,{children:"#void"})," is not false value."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(eq? (if #f #f) (values))\n;; ==> #t\n"})}),"\n",(0,a.jsx)(n.h2,{id:"numerical-tower",children:"Numerical tower"}),"\n",(0,a.jsx)(n.p,{children:"LIPS support full numerical tower (not yet 100% unit tested):"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsx)(n.li,{children:"integers - using BitInt"}),"\n",(0,a.jsx)(n.li,{children:"floats - using JavaScript numbers"}),"\n",(0,a.jsx)(n.li,{children:"rationals"}),"\n",(0,a.jsx)(n.li,{children:"complex numbers (that can use integers, floats, or rationals)"}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"print-procedure",children:"Print procedure"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define helper ",(0,a.jsx)(n.code,{children:"print"})," procedure that display all its arguments with newline after each element."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(print 1 2 3)\n;; ==> 1\n;; ==> 2\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.h2,{id:"emoji",children:"Emoji"}),"\n",(0,a.jsx)(n.p,{children:"LIPS fully supports all Unicode characters, including emoji:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define smiley #\\\ud83d\ude00)\n(define poo #\\\ud83d\udca9)\n(write (string-append (string smiley) " " (string poo)))\n;; ==> "\ud83d\ude00 \ud83d\udca9"\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also use them as part of symbols (e.g. as variables name):"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (\u23cf\ufe0f)\n (print "ejecting"))\n(\u23cf\ufe0f)\n;; ==> ejecting\n'})}),"\n",(0,a.jsx)(n.h2,{id:"macros",children:"Macros"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define both Lisp macros and Scheme hygienic macros (",(0,a.jsx)(n.code,{children:"syntax-rules"}),")."]}),"\n",(0,a.jsx)(n.p,{children:"It also implements:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-46/",children:"SRFI-46"})," which allows changing the ellipsis symbol for nested syntax-rules."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-139/",children:"SRFI-139"})," which allows defining\n",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#anaphoric-hygienic-macros",children:"anaphoric syntax-rules macros"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-147/",children:"SRFI-147"})," which allows defining a new syntax-rules macros to define syntax-rules macros."]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"gensyms",children:"Gensyms"}),"\n",(0,a.jsxs)(n.p,{children:["With lisp macros you can use ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#gensyms",children:"gensyms"}),", they are special Scheme\nsymbols that use JavaScript symbols behind the scene, so they are proven to be unique. Additionally\nyou can use named gensym if you pass string as first argument:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(gensym)\n;; ==> #:g5\n(gensym "sym")\n;; ==> #:sym\n'})}),"\n",(0,a.jsx)(n.h2,{id:"single-argument-eval",children:"Single argument eval"}),"\n",(0,a.jsxs)(n.p,{children:["Eval in LIPS don't require second argument to ",(0,a.jsx)(n.code,{children:"eval"}),". The environment is optional and default\nit's a result of calling ",(0,a.jsx)(n.code,{children:"(interaction-environment)"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(eval '(+ x x))\n;; ==> 20\n"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(let ((x 20))\n (eval '(- x)))\n;; ==> -10\n"})}),"\n",(0,a.jsx)(n.p,{children:"But you can also use the second arguments:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define x 10)\n(let ((x 20))\n (eval '(- x) (current-environment)))\n;; ==> -20\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Read more about ",(0,a.jsx)(n.a,{href:"/docs/lips/environments",children:"LIPS environments"}),"."]}),"\n",(0,a.jsx)(n.h2,{id:"procedures",children:"Procedures"}),"\n",(0,a.jsxs)(n.p,{children:["Procedures in LIPS have access additional objects ",(0,a.jsx)(n.code,{children:"arguments"}),", but the have nothing to do with JavaScript.\narguments is an array/vector with calling arguments and it have an object callee which points to the same\nprocedure. So you can create recursive functions with anonymous lambda:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"((lambda (n)\n (if (<= n 0)\n 1\n (* n (arguments.callee (- n 1))))) 10)\n;; ==> 3628800\n"})}),"\n",(0,a.jsx)(n.p,{children:"This is classic factorial function written as lambda without the name."}),"\n",(0,a.jsx)(n.h3,{id:"length-property",children:"length property"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS functions similarly to JavaScript functions also have ",(0,a.jsx)(n.code,{children:"length"})," property that indicate how many\narguments a function accepts. If function get more or less argumenets it's not an error like in Scheme. More arguments are ignored,\nand if less arguments are passed they are ",(0,a.jsx)(n.code,{children:"undefined"})," (",(0,a.jsx)(n.code,{children:"#void"}),")."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b c)\n (+ a b c))\n\n(print sum.length)\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.p,{children:"It return number of number arguments the rest (dot notation) arguments are ignored."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(define (sum a b . rest)\n (apply + a b rest))\n\n(print sum.length)\n;; ==> 3\n(sum 1 2 3 4 5 6)\n;; ==> 21\n"})}),"\n",(0,a.jsx)(n.h2,{id:"doc-strings",children:"Doc strings"}),"\n",(0,a.jsx)(n.p,{children:"Procedures, macros, and variables can have doc strings."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (factorial n)\n "(factorial n)\n\n Calculate factorial of a given number"\n (if (<= n 0)\n 1\n (* n (factorial (- n 1)))))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can access doc string with ",(0,a.jsx)(n.code,{children:"help"})," procedure or with ",(0,a.jsx)(n.code,{children:"__doc__"})," property."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(write factorial.__doc__)\n"(factorial n)\n\nCalculate factorial of a given number"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["If you define variable or hygienic macro with doc string, the string is hidden (you can access it with ",(0,a.jsx)(n.code,{children:"__doc__"}),"),\nso help is the only way to access it:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-syntax q\n (syntax-rules ()\n ((_ x) \'x))\n "(q expression)\n\n Macro quote the expression")\n\n(write q.__doc__)\n;; ==> #void\n(help q)\n;; ==> (q expression)\n;; ==>\n;; ==> Macro quote the expression\n'})}),"\n",(0,a.jsx)(n.h2,{id:"typechecking",children:"Typechecking"}),"\n",(0,a.jsx)(n.p,{children:"LIPS do typechecking for all scheme procedures."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(+ "hello" 10)\n;; ==> Expecting number got string\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can incorporate typechecking in your own code:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((x 10))\n (typecheck "let" x "string" 0))\n;; ==> Expecting string got number in expression `let` (argument 0)\n(let ((x "string"))\n (typecheck "let" x "number"))\n;; ==> Expecting number got string in expression `let`\n'})}),"\n",(0,a.jsx)(n.p,{children:"There is also another function to check type of number:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((i 10+10i))\n (typecheck-number "let" i "bigint"))\n;; ==> Expecting bigint got complex in expression `let`\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": In LIPS all integers are BigInts."]}),"\n",(0,a.jsxs)(n.p,{children:["The last typecking function is ",(0,a.jsx)(n.code,{children:"typecheck-args"})," that check if all arguments are of same type."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((number \'(1 10 1/2 10+10i)))\n (typecheck-args "number" "let" number))\n;; ==> #void\n(let ((number \'(1 10 1/2 "string")))\n (typecheck-args "number" "let" number))\n;; ==> Expecting number got string in expression `let` (argument 4)\n'})}),"\n",(0,a.jsx)(n.h2,{id:"integration-with-javascript",children:"Integration with JavaScript"}),"\n",(0,a.jsx)(n.h3,{id:"dot-notation",children:"Dot notation"}),"\n",(0,a.jsx)(n.p,{children:"LIPS allow accessing JavaScript objects with dot notation:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"document.querySelector\n;; ==> #\n"})}),"\n",(0,a.jsx)(n.h3,{id:"mutating-object-properties",children:"Mutating object properties"}),"\n",(0,a.jsxs)(n.p,{children:["You can use dot notation with ",(0,a.jsx)(n.code,{children:"set!"})," to change the value:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(set! self.foo 10)\nself.foo\n"})}),"\n",(0,a.jsxs)(n.p,{children:["top level ",(0,a.jsx)(n.code,{children:"self"})," always points to a global object ",(0,a.jsx)(n.code,{children:"window"})," in browser or ",(0,a.jsx)(n.code,{children:"global"})," in Node."]}),"\n",(0,a.jsxs)(n.p,{children:["There is also older API that still work, which is ",(0,a.jsx)(n.code,{children:"set-obj!"})," but with dot notation you don't\nneed it anymore:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(set-obj! self 'foo 10)\n(display self.foo)\n;; ==> 10\n"})}),"\n",(0,a.jsx)(n.p,{children:"In both platforms you can access global JavaScript objects like normal variables:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! self.greet "hello, LIPS")\n(write greet)\n;; ==> "hello, LIPS"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"date-and-time",children:"Date and Time"}),"\n",(0,a.jsxs)(n.p,{children:["Since we have full access to JavaScript, we can access the ",(0,a.jsx)(n.code,{children:"Date"})," object to manipulate date and time."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (new Date "2024-01-01 12:09:2")\n (getFullYear))\n;; ==> 2024\n'})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define (format-part number)\n "(format-part number)\n\n Convert number to string with leading zero. It should be used\n for minutes, hours, and seconds."\n (--\x3e number (toString) (padStart 2 "0")))\n\n(let ((date (new Date "2024-01-01 12:09:02")))\n (format "~a:~a:~a"\n (format-part (date.getHours))\n (format-part (date.getMinutes))\n (format-part (date.getSeconds))))\n;; ==> "12:09:02"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also use Date time libraries like ",(0,a.jsx)(n.a,{href:"https://date-fns.org/",children:"date-fns"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"interact-with-dom",children:"Interact with DOM"}),"\n",(0,a.jsxs)(n.p,{children:["Here is example how to add button to the page and add onclick handler using browser DOM\n(",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model",children:"Document Object Model"}),") API."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((button (document.createElement "button")))\n (set! button.innerHTML "click me!")\n (set! button.onclick (lambda () (alert "Hello, LIPS Scheme!")))\n (let ((style button.style))\n (set! style.position "absolute")\n (set! style.zIndex 9999)\n (set! style.top 0)\n (set! style.left 0))\n (document.body.appendChild button))\n'})}),"\n",(0,a.jsx)(n.h3,{id:"boxing",children:"Boxing"}),"\n",(0,a.jsx)(n.p,{children:"LIPS have its own representation for numbers, strings and characters. And when\ninteracting with JavaScript the values may get boxed or unboxed automagically."}),"\n",(0,a.jsxs)(n.p,{children:["You should not confuse boxing with boxes (",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-111/",children:"SRFI-111"})," and\n",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-195",children:"SRFI-195"}),"). LIPS boxing are part of implementation of Scheme\ndata types. And SRFI boxes are containers written in Scheme. Name boxing came from JavaScript, when\nprimitive values are wrapped in objects when you try to use them in object context (like accessing\na property)."]}),"\n",(0,a.jsx)(n.p,{children:"You need to be careful with some of the JavaScript native methods, since they can unbox the value when you don't\nwhen them to be unboxed."}),"\n",(0,a.jsxs)(n.p,{children:["Example is ",(0,a.jsx)(n.code,{children:"Array::push"})," using with native LIPS types:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((v (vector)))\n (v.push 1/2)\n (print v))\n;; ==> #(0.5)\n"})}),"\n",(0,a.jsx)(n.p,{children:"As you can see the rational number got unboxed and converted into JavaScript float numbers.\nUnboxing always can make you loose some information because LIPS types needs to be converted into native JavaScript\ndata types. And JavaScript doesn't have a notion of rationals, there are only floating point numbers, and big ints."}),"\n",(0,a.jsx)(n.h3,{id:"procedures-1",children:"Procedures"}),"\n",(0,a.jsx)(n.p,{children:"LIPS Scheme procedures are JavaScript functions, so you can call them from JavaScript."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! self.greet (lambda () "hello, LIPS"))\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can call this function from JavaScript"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"console.log(greet());\n// ==> {__string__: 'hello, LIPS'}\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Note that the value was not automagically unboxed because we are no longer in LIPS Scheme code and LIPS can't access native\nJavaScript. So to get the real a string you need to call ",(0,a.jsx)(n.code,{children:"valueoOf()"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"console.log(greet().valueOf());\n// ==> hello, LIPS\n"})}),"\n",(0,a.jsx)(n.h4,{id:"procedure-arity",children:"Procedure arity"}),"\n",(0,a.jsx)(n.p,{children:"LIPS don't check the number of argumnents when calling a procedure:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((test (lambda (a b c)\n (print a b c))))\n (test 10))\n;; ==> 10\n;; ==> #void\n;; ==> #void\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The same as with JavaScript if you don't pass an argument it will be undefined. But you still have full compatible with Scheme and use ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#variable-number-of-arguments",children:"arguments with variable artity"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((test (lambda (first . rest)\n (apply print first rest))))\n (test 1)\n (test 2 3 4))\n;; ==> 1\n;; ==> 2\n;; ==> 3\n;; ==> 4\n"})}),"\n",(0,a.jsx)(n.h3,{id:"helper-macros-and-functions",children:"Helper macros and functions"}),"\n",(0,a.jsxs)(n.p,{children:["The most useful macro in LIPS (for interacting with JavaScript) is ",(0,a.jsx)(n.code,{children:"--\x3e"})," it acts like a chain of\nmethod calls in JavaScript"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e "this is string" (split " ") (reverse) (join " "))\n;; ==> "string is this"\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can chain methods that return arrays or string and call a method of them. The above expression\nis the same as JavaScript:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:"\"this is string\".split(' ').reverse().join(' ');\n"})}),"\n",(0,a.jsx)(n.p,{children:"With --\x3e you can also gab property of a function:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #/x/ (test.call #/foo/ "foo"))\n;; ==> #t\n(let ((test-bar (--\x3e #/x/ (test.bind #/bar/i))))\n (test-bar "BAR"))\n;; ==> #t\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also return a function:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define test (--\x3e #/x/ test))\n(test.call #/foo/ "foo")\n;; ==> #t\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Read more about ",(0,a.jsx)(n.a,{href:"https://tinyurl.com/ykvb836s",children:"function::bind"})," and\n",(0,a.jsx)(n.a,{href:"https://tinyurl.com/yc6j7fdh",children:"function::call"})," on ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/",children:"MDN"}),"."]}),"\n",(0,a.jsx)(n.h4,{id:"legacy-macros-and-functions",children:"Legacy macros and functions"}),"\n",(0,a.jsx)(n.p,{children:"There are two legacy macros that are still part of LIPS, but you don't need\nthem most of the time."}),"\n",(0,a.jsx)(n.h5,{id:"the-dot-operator",children:"The dot operator"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"."})," - dot function was a first way to interact with JavaScript, it allowed to get property from an\nobject:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(. document 'querySelector)\n"})}),"\n",(0,a.jsxs)(n.p,{children:["This returned function querySelector from document object in browser. Note that dot a function can only appear\nas first element of the list (it's handled in special way by the parser). In any other place dot is a pair separator,\nsee documentation about ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/data-types#pairs",children:"Pairs in Scheme"}),"."]}),"\n",(0,a.jsx)(n.h5,{id:"the-double-dot-operator",children:"The double dot operator"}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:".."})," - this is a macro is that simplify usage of ",(0,a.jsx)(n.code,{children:"."})," procedure:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(.. document.querySelector)\n"})}),"\n",(0,a.jsxs)(n.h5,{id:"usage-of-legacy--and--operators",children:["Usage of Legacy ",(0,a.jsx)(n.code,{children:".."})," and ",(0,a.jsx)(n.code,{children:"."})," operators"]}),"\n",(0,a.jsxs)(n.p,{children:["You still sometimes may want to use ",(0,a.jsx)(n.code,{children:"."})," instead of ",(0,a.jsx)(n.code,{children:"--\x3e"})," when you want to get\nproperty from an object returned by expression."]}),"\n",(0,a.jsx)(n.p,{children:"In the old version of LIPS, you have to execute code like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'((. document \'querySelector) "body")\n((.. document.querySelector) "body")\n'})}),"\n",(0,a.jsx)(n.p,{children:"The first expression return a Native JavaScript procedure that is then executed."}),"\n",(0,a.jsx)(n.p,{children:"This is equivalent of:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(document.querySelector "body")\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," the only time when you still need ",(0,a.jsx)(n.code,{children:"."})," function is when you want to get the property of\nobject returned by expression."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((style (. (document.querySelector "body") \'style)))\n (set! style.background "red"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Here we get a ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style",children:"style object"}),"\nfrom ",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement",children:"the DOM node"})," without sorting the\nreference to the DOM node."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," because dot notation in symbols is not special syntax you can use code like this:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((x #(1 2 3)))\n (print x.0)\n (print x.1)\n (print x.2))\n;; ==> 1\n;; ==> 2\n;; ==> 3\n"})}),"\n",(0,a.jsx)(n.h3,{id:"scheme-functions",children:"Scheme functions"}),"\n",(0,a.jsx)(n.p,{children:"Scheme functions (lambda's) are JavaScript functions, so you can call them from JavaScript."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! window.foo (lambda () (alert "hello")))\n'})}),"\n",(0,a.jsx)(n.p,{children:"If you define function like this, in browser REPL, you can call it from JavaScript\n(e.g. browser developer console)."}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"TODO"})," Screenshot"]}),"\n",(0,a.jsx)(n.h3,{id:"javascript-functions",children:"JavaScript functions"}),"\n",(0,a.jsx)(n.p,{children:"You can call JavaScript functions from Scheme, the same as you call Scheme procedures:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(document.querySelector "body")\n;; ==> #\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In both browser and Node.js you can execute ",(0,a.jsx)(n.code,{children:"console.log"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(console.log "hello, LIPS")\n;; ==> hello, LIPS\n'})}),"\n",(0,a.jsx)(n.h3,{id:"callbacks",children:"Callbacks"}),"\n",(0,a.jsx)(n.p,{children:"You can use Scheme functions as callbacks to JavaScript functions:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map string->number))\n;; ==> #(1 +nan.0 +nan.0)\n'})}),"\n",(0,a.jsx)(n.p,{children:"This is classic issue with functions that accept more than one argument. You have samilar issue\nin JavaScript:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'["1", "2", "3"].map(parseInt)\n// ==> [1, NaN, NaN]\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": the value are different becaseu in Shceme i"]}),"\n",(0,a.jsx)(n.p,{children:"To fix the issue you can\ndefine lambda with single argument:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map (lambda (str) (string->number str))))\n;; ==> #(1 2 3)\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also use one of functional helpers insprired by ",(0,a.jsx)(n.a,{href:"https://ramdajs.com/",children:"Ramda"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("1" "2" "3") (map (unary string->number)))\n;; ==> #(1 2 3)\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"unary"})," ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#higher-order-functions",children:"higher-order procedure"})," accept a single\nprocedure and return new procedure that accept only one argument."]}),"\n",(0,a.jsxs)(n.p,{children:["To read more check ",(0,a.jsx)(n.a,{href:"/docs/lips/functional-helpers",children:"Functional helpers"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"WARNING"})," be careful when using scheme callback functions inside JavaScript.\nSince some code may be ",(0,a.jsx)(n.code,{children:"async"})," and your code may break."]}),"\n",(0,a.jsx)(n.p,{children:"Example of procedures that are not wise to use are:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"Array::forEach"})," - this function accepts a callaback but because it doesn't return\nanything, LIPS can't automatically await the response, and your code may execute out of order."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"String::replace"})," - this function can accept optional callback and if ",(0,a.jsx)(n.code,{children:"lambda"})," is async\nyou will end up with ",(0,a.jsx)(n.code,{children:"[object Promise]"})," in output string. Any macro or function can return\na promise in LIPS, and if any of the expression inside a function return a Promise, the whole\nfunction return a Promise and become async. Here is example code that demonstrate the problem:"]}),"\n"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e "foo bar" (replace "foo" (lambda () (Promise.resolve "xxx"))))\n"[object Promise] bar"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Instead of ",(0,a.jsx)(n.code,{children:"Array::replace"})," you should use LIPS Scheme ",(0,a.jsx)(n.code,{children:"replace"})," procedure that works with async ",(0,a.jsx)(n.code,{children:"lambda"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(replace #/[a-z]+/g (lambda ()\n (Promise.resolve "lips"))\n "foo bar")\n;; ==> "lips lips"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"regular-expressions",children:"Regular Expressions"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS define regular expressions it uses native JavaScript regular expressions.\nAt first, the syntax looked like in JavaScript. It was problematic for the parser\nso you were not able to put space after ",(0,a.jsx)(n.code,{children:"/"})," to distinguish from divide procedure.\nLater, the syntax was renamed into form that start with hash ",(0,a.jsx)(n.code,{children:"#/[0-9]/"}),". The same\nsyntax is used by ",(0,a.jsx)(n.a,{href:"https://practical-scheme.net/gauche/man/gauche-refe/Regular-expressions.html",children:"Gauche"})," implementation. But LIPS supports more flags (same as JavaScript)."]}),"\n",(0,a.jsx)(n.h3,{id:"vectors",children:"Vectors"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS Scheme vectors are JavaScript arrays. So you can execute methods on them with ",(0,a.jsx)(n.code,{children:"--\x3e"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e #("one" "two" "three") (join ":"))\n;; ==> "one:two:three"\n'})}),"\n",(0,a.jsx)(n.h3,{id:"object-literals",children:"Object literals"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS you can define object literals with ",(0,a.jsx)(n.code,{children:"&"}),"\n",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extension"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name "Jack" :age 22))\n(write obj)\n;; ==> &(:name "Jack" :age 22)\n(console.log obj)\n;; ==> { name: \'Jack\', age: 22 }\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can nest object literals and mix them with different object:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name "Jack" :hobbies #("swimming" "programming")))\n(write obj.hobbies)\n;; ==> #("swimming" "programming")\n(console.log obj)\n;; ==> { name: \'Jack\', hobbies: [ \'swiming\', \'programming\' ] }\n'})}),"\n",(0,a.jsx)(n.p,{children:"Object similar to Scheme vectors, are immutable, and everything inside is quoted automatically:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define obj &(:name Jack))\n(write obj)\n;; ==> &(:name "Jack")\n'})}),"\n",(0,a.jsx)(n.p,{children:"But to make it possible to share objects with JavaScript, native LIPS values are automatically unboxed.\nSo instead of symbol representation you get a JavaScript string."}),"\n",(0,a.jsx)(n.p,{children:"You can also use quasiquote with object literals:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define jack (let ((name "Jack")\n (age 22))\n `&(:name ,name :age ,age)))\n(write jack)\n;; ==> &(:name "Jack" :age 22)\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": because of the construction of ",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extensions"})," and\n",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/data-types#quasiquote",children:"quasiquote"}),", you can't splice a list inside object literals:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((args (list \':foo "lorem" \':bar "ipsum")))\n `&(,@args))\n;; ==> pair (unquote-splicing args) is not a symbol!\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The reason why this work like this is because, syntax extensions (",(0,a.jsx)(n.code,{children:"&"}),") runs at parse time and LIPS macros are runtime.\nThis may change in the future when ",(0,a.jsx)(n.a,{href:"https://github.com/jcubic/lips/issues/169",children:"expansion time will be implemented"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["Objects also have longhand form with ",(0,a.jsx)(n.code,{children:"object"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((obj (object :name \'Jack)))\n (write obj))\n;; ==> &(:name "Jack")\n'})}),"\n",(0,a.jsx)(n.p,{children:"But note that object macro is async (return a Promise) so it may be problematic when used it\nwith native JavaScript code."}),"\n",(0,a.jsxs)(n.p,{children:["Using long form ",(0,a.jsx)(n.code,{children:"(object)"})," syntax you can use splicing with help of ",(0,a.jsx)(n.code,{children:"eval"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((args \'(:foo "lorem" :bar "ipsum")))\n (eval `(object ,@args)))\n;; ==> &(:foo "lorem" :bar "ipsum")\n'})}),"\n",(0,a.jsx)(n.p,{children:"The same you can use macros that will return LIPS Scheme code:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-macro (create-object . args)\n `(object ,@args))\n\n(create-object :foo "lorem" :bar "ipsum")\n;; ==> &(:foo "lorem" :bar "ipsum")\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": this example macro works the same ",(0,a.jsx)(n.code,{children:"object"})," is it's not that useful, but you can create\nmore complex code where you will be able to generate object literals with splicing."]}),"\n",(0,a.jsx)(n.p,{children:"Object literal also have shorthad notation:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj &(:x :y)))\n (write obj))\n;; ==> &(:x #void :y #void)\n"})}),"\n",(0,a.jsx)(n.p,{children:"It creates two writtable slots, the rest of the props are read only:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj &(:x :y)))\n (set! obj.x 10)\n (set! obj.y 20)\n (write obj))\n;; ==> &(:x 10 :y 20)\n\n(let ((obj &(:x :y)))\n (set! obj.z 20)\n (write obj))\n;; ==> Cannot add property z, object is not extensible\n\n(let ((obj &(:x :y :z 10)))\n (set! obj.z 20)\n (write obj))\n;; ==> Cannot assign to read only property 'z' of object '#'\n"})}),"\n",(0,a.jsx)(n.h3,{id:"automagic-asyncawait",children:"Automagic async/await"}),"\n",(0,a.jsx)(n.p,{children:"LIPS do automatic async/await so it waits for any promise before evaluating\nnext expression."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(Promise.resolve "xxx")\n;; ==> "xxx"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["This simplifies code when using promises, for instance using\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API",children:"fetch API"})," (AJAX)."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (fetch "https://scheme.org.pl/test/") (text) (match #/

([^>]+)<\\/h1>/) 1)\n;; ==> "Scheme is Super Fun"\n'})}),"\n",(0,a.jsx)(n.p,{children:"This is equivalent of JavaScript using async/await:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'cons res = await fetch("https://scheme.org.pl/test/");\nconst text = await res.text();\ntext.match(/

([^>]+)<\\/h1>/)[1];\n'})}),"\n",(0,a.jsx)(n.h3,{id:"promise-quotation",children:"Promise quotation"}),"\n",(0,a.jsxs)(n.p,{children:["Sometimes you need to process promises as values, for this LIPS support quotation\nof promises. You escape automagic async/await realm and get access to promise as value:\nto quote a promise you use ",(0,a.jsx)(n.code,{children:"'>"}),"\n",(0,a.jsx)(n.a,{href:"/docs/lips/extension#syntax-extensions",children:"syntax extension"}),". To again get into\nautomatic async/await you can use ",(0,a.jsx)(n.code,{children:"(await)"})," procedure"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(let ((promise (--\x3e \'>(fetch "https://scheme.org.pl/test/")\n (then (lambda (res)\n (res.text)))\n (then (lambda (text)\n (. (text.match #/

([^>]+)<\\/h1>/) 1))))))\n (print (await promise)))\n;; ==> Scheme is Super Fun\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," Inside ",(0,a.jsx)(n.code,{children:"then"})," lambda promises are still automagically resolved."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e \'>(Promise.resolve "hello")\n (then (lambda (value)\n (print (string-append value " " (Promise.resolve "LIPS"))))))\n;; ==> hello LIPS\n'})}),"\n",(0,a.jsx)(n.h3,{id:"promises-vs-delay-expression",children:"Promises vs delay expression"}),"\n",(0,a.jsxs)(n.p,{children:["Don't confuse JavaScript promises with ",(0,a.jsx)(n.code,{children:"delay"})," expressions. Their representation looks similar:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(delay 10)\n;; ==> #\n'>(Promise.resolve 10)\n;; ==> #\n"})}),"\n",(0,a.jsxs)(n.p,{children:["You can check if a value is a promise by quoting the expression and using ",(0,a.jsx)(n.code,{children:"promise?"})," predicate:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((a '>10)\n (b '>(Promise.resolve 10)))\n (print (promise? a))\n (print (promise? b)))\n;; ==> #f\n;; ==> #t\n"})}),"\n",(0,a.jsx)(n.h3,{id:"exceptions",children:"Exceptions"}),"\n",(0,a.jsx)(n.p,{children:"LIPS Scheme use javascript exception system. To throw an exception you use:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(throw "This is error")\n;; ==> Error: This is error\n'})}),"\n",(0,a.jsx)(n.p,{children:"or"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(raise (new Error "error"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"raise"})," procedure throw any object and ",(0,a.jsx)(n.code,{children:"throw"})," wraps the argument in ",(0,a.jsx)(n.code,{children:"new Error"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"You can catch exceptions with LIPS specific try..catch..finally:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (catch (e)\n (print (string-append "error " e.message " was caught"))))\n;; ==> error nasty was caught\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can also have finally expression:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (catch (e)\n (print (string-append "error " e.message " was caught")))\n (finally\n (print "nothing happened")))\n;; ==> error nasty was caught\n;; ==> nothing happened\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also define ",(0,a.jsx)(n.code,{children:"finally"})," without ",(0,a.jsx)(n.code,{children:"catch"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(try\n (throw "nasty")\n (finally\n (print "after error")))\n;; ==> after error\n;; ==> nasty\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"})," the order of execution is not expected, but it may change in the future."]}),"\n",(0,a.jsxs)(n.p,{children:["LIPS also define R",(0,a.jsx)("sup",{children:"7"}),"RS guard ",(0,a.jsx)(n.code,{children:"procedure"})," that is just a macro that use try..catch behind the scene:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(guard (e ((list? e) (print (string-append "Error: " (car e)))))\n (raise \'("error")))\n;; ==> Error: error\n'})}),"\n",(0,a.jsx)(n.h3,{id:"javascript-generars-and-iterators",children:"JavaScript Generars and iterators"}),"\n",(0,a.jsxs)(n.p,{children:["Right now there is no way to define JavaScript generators inside LIPS. You can create iterator using\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols",children:"iteration prorocol"}),",\nBut to have yield keyword you need ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/continuations",children:"continuations"}),", they are part of the\nLIPS Roadmap."]}),"\n",(0,a.jsx)(n.p,{children:"Here is example of creating iterator in LIPS:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(let ((obj (object))\n (max 5))\n (set-obj! obj Symbol.iterator\n (lambda ()\n (let ((i 0))\n `&(:next ,(lambda ()\n (set! i (+ i 1))\n (if (> i max)\n `&(:done #t)\n `&(:done #f :value ,(/ 1 i))))))))\n (print (iterator->array obj))\n (print (Array.from obj)))\n;; ==> #(1 1/2 1/3 1/4 1/5)\n;; ==> #(1 1/2 1/3 1/4 1/5)\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"Array.from"})," can't be used for every possible case because it will unbox the values (and convert\nrational to float), here it doesn't happen because LIPS don't treat JavaScript iterators in any\nspecial way (it may change in the future). But ",(0,a.jsx)(n.code,{children:"Array.from"})," will convert the array of rationals to\nfloat if used on normal vector:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:"(Array.from #(1/2 1/3 1/4 1/5))\n;; ==> #(0.5 0.3333333333333333 0.25 0.2)\n"})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": be careful when using iterator protocol because any function side Scheme can return a promise. If you would change\nquoted object literal ",(0,a.jsx)(n.code,{children:"`&()"})," with longhand ",(0,a.jsx)(n.code,{children:"object"})," you will get an error because ",(0,a.jsx)(n.code,{children:"object"})," is async."]}),"\n",(0,a.jsxs)(n.p,{children:["You can abstract the use of iteration protocol with a macro, but to have real ",(0,a.jsx)(n.code,{children:"yield"})," keyword like\nsyntax you need ",(0,a.jsx)(n.code,{children:"call/cc"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also define generators inside JavaScript using ",(0,a.jsx)(n.code,{children:"self.eval"})," (JavaScript global ",(0,a.jsx)(n.code,{children:"eval"}),"):"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define gen (self.eval "(async function* gen(time, ...args) {\n function delay(time) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n }\n for (let x of args) {\n await delay(time);\n yield x;\n }\n })"))\n\n(iterator->array (gen 100 1 2 3 4 5))\n;; ==> #(1 2 3 4 5)\n'})}),"\n",(0,a.jsx)(n.p,{children:"Here is example of async generator written in JavaScript."}),"\n",(0,a.jsx)(n.h3,{id:"classes",children:"Classes"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS, you can define JavaScript classes with ",(0,a.jsx)(n.code,{children:"define-class"})," macro:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define-class Person Object\n (constructor (lambda (self name)\n (set! self.name name)))\n (greet (lambda (self)\n (string-append "hello, " self.name))))\n\n(define jack (new Person "Jack"))\n(write jack)\n;; ==> #\n(jack.greet)\n;; ==> "hello, Jack"\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.code,{children:"define-class"})," is macro written in Scheme that uses\n",(0,a.jsx)(n.a,{href:"https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes",children:"JavaScript prototypes"})," behind the scene."]}),"\n",(0,a.jsxs)(n.p,{children:["The class always need to have a base class (parent) or you need to use ",(0,a.jsx)(n.code,{children:"null"}),". Classes have explicit\n",(0,a.jsx)(n.code,{children:"self"})," as first argument (similar to Python) but ",(0,a.jsx)(n.code,{children:"this"})," also works inside functions:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(set! jack.run (lambda () (string-append "run, " this.name)))\n(jack.run)\n;; ==> "run, Jack"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["To create the new instance of a Class, you can use ",(0,a.jsx)(n.code,{children:"new"})," procedure."]}),"\n",(0,a.jsx)(n.p,{children:"You can also manipulate JavaScript prototypes directly:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(write Person.prototype)\n;; ==> #\n(set! Person.prototype.toString (lambda () (string-append "#")))\n(display (jack.toString))\n;; ==> #\n'})}),"\n",(0,a.jsxs)(n.p,{children:["By default toString is not used for representation of objects, but you add representation if you want.\nSee ",(0,a.jsx)(n.a,{href:"/docs/lips/extension#new-homoiconic-data-types",children:"Homoiconic data types"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"nodejs",children:"Node.js"}),"\n",(0,a.jsxs)(n.p,{children:["In Node.js, you can load JavaScript modules with ",(0,a.jsx)(n.code,{children:"require"}),":"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define fs (require "fs/promises"))\n(let ((fname "tmp.txt"))\n (fs.writeFile fname "hello LIPS")\n (write (fs.readFile fname "utf-8")))\n;; ==> "hello LIPS"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In above code, you can see example of ",(0,a.jsx)(n.a,{href:"#automagic-asyncawait",children:"automagic async/await"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["If you have to use callback based API in Node, use\n",(0,a.jsx)(n.a,{href:"https://nodejs.org/api/util.html#utilpromisifyoriginal",children:"promisify function"})," from Module util."]}),"\n",(0,a.jsxs)(n.p,{children:["You can also use the ",(0,a.jsx)(n.code,{children:"Promise"})," constructor yourself:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define fs (require "fs"))\n\n(define-macro (async expr)\n (let ((resolve (gensym "resolve"))\n (reject (gensym "reject")))\n `(new Promise (lambda (,resolve ,reject)\n ,(append expr (list `(lambda (err data)\n ;; Node.js error is null when no error\n (if err\n (,reject err)\n (,resolve data)))))))))\n\n(let ((fname "tmp.txt"))\n (async (fs.writeFile fname "Hello, LIPS!"))\n (write (async (fs.readFile fname "utf-8"))))\n;; ==> "Hello, LIPS!"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["In the above example, we import a regular callback based fs module and use the ",(0,a.jsx)(n.code,{children:"Promise"})," constructor\nabstracted away with a ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/macros#lisp-macros",children:"lisp macro"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"es-modules",children:"ES Modules"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS Scheme runs in ES Module, but ",(0,a.jsx)(n.code,{children:"import"})," is reserved for experimental R7RS modules. If you want\nto import module that is ESM only. You need to access JavaScript dynamic import. But ",(0,a.jsx)(n.code,{children:"global.import"})," is not defined. If you want to define JavaScript dynamic import, you can use code:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(define $:import (global.eval "(x) => import(x)"))\n'})}),"\n",(0,a.jsx)(n.p,{children:"You can use this function like this:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-javascript",children:'(--\x3e ($:import "fs/promises") (readFile "README.md" "utf8"))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["But it will also work with ESM only module that can't be imported with ",(0,a.jsx)(n.code,{children:"require"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"finding-lips-scheme-directory",children:"Finding LIPS Scheme directory"}),"\n",(0,a.jsxs)(n.p,{children:["With help from ",(0,a.jsx)(n.code,{children:"(require.resolve)"})," you can get the path of the root directory of LIPS Scheme:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(--\x3e (require.resolve "@jcubic/lips") (replace #/dist\\/[^\\/]+$/ ""))\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Node.js REPL load lips from Common.jS file and ",(0,a.jsx)(n.code,{children:"require.resolve"})," returns path to file\n",(0,a.jsx)(n.code,{children:"dist/lips.cjs"}),", by removing with with String::replace and regular expression you can the real path\nto the root of the LIPS Scheme."]}),"\n",(0,a.jsx)(n.h2,{id:"binary-compiler",children:"Binary compiler"}),"\n",(0,a.jsxs)(n.p,{children:["LIPS Scheme have dumb binary compiler. The compiler is a way to compress the LIPS Scheme code and\ncreate binary file that is faster to load. Compiler is use to make bootstrapping faster. The binary\nfile use ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/CBOR",children:"CBOR"})," serialization format that is then compressed\nwith ",(0,a.jsx)(n.a,{href:"https://en.wikipedia.org/wiki/LZJB",children:"LZJB"})," algorithm that is pretty fast. And it can still be\ncompress further with gzip by the HTTP server."]}),"\n",(0,a.jsxs)(n.p,{children:["To compile/compress a file you can use ",(0,a.jsx)(n.code,{children:"-c"})," flag when executing ",(0,a.jsx)(n.code,{children:"lips"})," executable."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"$ lips -c file.scm\n"})}),"\n",(0,a.jsx)(n.p,{children:"You can then execute the code with:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"$ lips -c file.xcb\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Will create ",(0,a.jsx)(n.code,{children:"file.xcb"})," in same directory. For smaller files it make not have a difference when\nloading ",(0,a.jsx)(n.code,{children:".xcb"})," or ",(0,a.jsx)(n.code,{children:".scm"})," files."]}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"NOTE"}),": directives ",(0,a.jsx)(n.code,{children:"#!fold-case"})," and ",(0,a.jsx)(n.code,{children:"#!no-fold-case"})," work only inside the parser and they are\ntreated as comments, so you can't compile the code that have those directives."]}),"\n",(0,a.jsx)(n.h2,{id:"loading-srfi",children:"loading SRFI"}),"\n",(0,a.jsxs)(n.p,{children:["In LIPS, you can use ",(0,a.jsx)(n.code,{children:"(load)"})," with path absolute or relative to the directory of the executed LIPS\nfile. But you can use special syntax that indicate the root directory of the LIPS Scheme."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-scheme",children:'(load "@lips/lib/srfi/1.scm")\n'})}),"\n",(0,a.jsxs)(n.p,{children:["This will load the code from ",(0,a.jsx)(n.a,{href:"https://srfi.schemers.org/srfi-1/srfi-1.html",children:"SRFI-1"})," List\nLibrary. You can use this syntax in Node based REPL (NPM executable). The same syntax should work\nwith the web. But note that the root directory reply on the path of the LIPS Scheme script file. So\nyou if you bundle the code with Webpack or Rollup, LIPS may not find the root URL and may not be\nable to load the proper file."]}),"\n",(0,a.jsx)(n.h2,{id:"limitations",children:"Limitations"}),"\n",(0,a.jsxs)(n.p,{children:["LISP Scheme currently don't support ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/continuations",children:"continuations"})," and ",(0,a.jsx)(n.a,{href:"/docs/scheme-intro/core#tail-call-optimization",children:"Tail Call\nOptimization"}),". But they are part of the roadmap for\nversion 1.0."]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>t,x:()=>c});var r=s(6540);const a={},i=r.createContext(a);function t(e){const n=r.useContext(i);return r.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(a):e.components||a:t(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.20f5ee6a.js b/assets/js/runtime~main.a64e70e2.js similarity index 65% rename from assets/js/runtime~main.20f5ee6a.js rename to assets/js/runtime~main.a64e70e2.js index 66061f7a..71e14a61 100644 --- a/assets/js/runtime~main.20f5ee6a.js +++ b/assets/js/runtime~main.a64e70e2.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:"8f697f91",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:"00d19001",4813:"1928affb",5011:"3fa53997",5742:"f5d4ac8d",5929:"afb107d6",6271:"51b5a57e",6365:"c648f275",6372:"711ebda3",6440:"6d175597",6580:"9d4051dd",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:"47320509",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,r,c,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,r,c)=>{if(!t){var f=1/0;for(i=0;i=c)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(b=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[t,r,c]},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,r){if(1&r&&(e=this(e)),8&r)return e;if("object"==typeof e&&e){if(4&r&&e.__esModule)return e;if(16&r&&"function"==typeof e.then)return e}var c=Object.create(null);d.r(c);var f={};a=a||[null,t({}),t([]),t(t)];for(var b=2&r&&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(c,f),c},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:"442699c4",849:"e79d03cd",1235:"35651660",1903:"bd6470b3",1933:"8f697f91",2237:"66fcbfbc",2272:"2bf1e156",2301:"27284ffb",2711:"c809fcd6",2866:"91265fd4",3249:"83e04d21",3347:"18dfe3b9",3484:"c938df1a",3789:"0a3e15cb",3976:"660f9d11",4044:"d15f09bb",4212:"af8ccb67",4413:"ae4b00d1",4583:"00d19001",4813:"1928affb",5011:"3fa53997",5742:"f5d4ac8d",5929:"afb107d6",6271:"51b5a57e",6365:"c648f275",6372:"711ebda3",6440:"6d175597",6580:"9d4051dd",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:"fcbe341c",8209:"5200d571",8401:"42d5ed25",8553:"dfe58b8e",8649:"4bfa6453",8691:"405f8d17",8913:"a77cc8d9",8947:"e6f6be2e",9048:"d90b76ed",9067:"b56915bc",9204:"c464cf32",9263:"47320509",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),r={},c="new-docs:",d.l=(e,a,t,f)=>{if(r[e])r[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 c=r[e];if(delete r[e],b.parentNode&&b.parentNode.removeChild(b),c&&c.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 r=d.o(e,a)?e[a]:void 0;if(0!==r)if(r)t.push(r[2]);else if(/^(1869|5354)$/.test(a))e[a]=0;else{var c=new Promise(((t,c)=>r=e[a]=[t,c]));t.push(r[2]=c);var f=d.p+d.u(a),b=new Error;d.l(f,(t=>{if(d.o(e,a)&&(0!==(r=e[a])&&(e[a]=void 0),r)){var c=t&&("load"===t.type?"missing":t.type),f=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+c+": "+f+")",b.name="ChunkLoadError",b.type=c,b.request=f,r[1](b)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var r,c,f=t[0],b=t[1],o=t[2],n=0;if(f.some((a=>0!==e[a]))){for(r in b)d.o(b,r)&&(d.m[r]=b[r]);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 c943d418..1098b940 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 3c50074e..036e7a9a 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 466142a0..7a512a63 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 24ffde6b..5b9a29cf 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 d63482dc..1fc4afe1 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 bfea89bb..a5e695f8 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 8044a062..d04559e3 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 7f1cf44b..8313aba5 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 beca69e1..c275d252 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 96b61cba..f4d35023 100644 --- a/docs/category/introduction-to-scheme.html +++ b/docs/category/introduction-to-scheme.html @@ -4,10 +4,10 @@ Introduction to Scheme | LIPS Scheme - + - + \ No newline at end of file diff --git a/docs/category/lips-introduction.html b/docs/category/lips-introduction.html index 9c477035..60fb5421 100644 --- a/docs/category/lips-introduction.html +++ b/docs/category/lips-introduction.html @@ -3,11 +3,11 @@ -LIPS introduction | LIPS Scheme - +LIPS Documentation | LIPS Scheme + - + \ No newline at end of file diff --git a/docs/intro.html b/docs/intro.html index df46330a..34cb6831 100644 --- a/docs/intro.html +++ b/docs/intro.html @@ -4,11 +4,11 @@ Getting Started | LIPS Scheme - + -

Getting Started

+

Getting Started

Browser

When using the LIPS Scheme interpreter in a browser, you need to include the main script file.

<script src="https://unpkg.com/@jcubic/lips@beta/dist/lips.min.js"></script>
diff --git a/docs/lips/REPL.html b/docs/lips/REPL.html
index bf7ebacc..61dc9204 100644
--- a/docs/lips/REPL.html
+++ b/docs/lips/REPL.html
@@ -4,11 +4,11 @@
 
 
 REPL | LIPS Scheme
-
+
 
 
 
-

REPL

+

REPL

LIPS Scheme REPL (Read Even Print Loop) is a way to interact with running LIPS Scheme session.

Web REPL

diff --git a/docs/lips/SRFI.html b/docs/lips/SRFI.html index da37dd5d..1cc647bf 100644 --- a/docs/lips/SRFI.html +++ b/docs/lips/SRFI.html @@ -4,11 +4,11 @@ SRFI | LIPS Scheme - + -

SRFI

+

SRFI

Builtin SRFI

This is a list of builin SRFI that don't require any action from user:

descriptionspec
Feature-based conditional expansion constructSRFI-0
Homogeneous numeric vector datatypesSRFI-4
Basic String PortsSRFI-6
Running Scheme Scripts on UnixSRFI-22
Error reporting mechanismSRFI-23
Basic Format StringsSRFI-28
Basic Syntax-rules ExtensionsSRFI-46
An interface to access environment variablesSRFI-98
Syntax parametersSRFI-139
Custom macro transformersSRFI-147
Version flagSRFI-176
Command lineSRFI-193
diff --git a/docs/lips/embeding-repl.html b/docs/lips/embeding-repl.html index 8558f944..8428329f 100644 --- a/docs/lips/embeding-repl.html +++ b/docs/lips/embeding-repl.html @@ -4,11 +4,11 @@ Embedding LIPS REPL | LIPS Scheme - + -

Embedding LIPS REPL

+

Embedding LIPS REPL

To embed the LIPS REPL you need on your website you need:

A HTML Web page

First you need to have a website where you want to embed the REPL. You can create simple HTML page diff --git a/docs/lips/environments.html b/docs/lips/environments.html index 55beb603..6c39c8a3 100644 --- a/docs/lips/environments.html +++ b/docs/lips/environments.html @@ -4,11 +4,11 @@ Environments | LIPS Scheme - + -

Environments

+

Environments

Environments in LIPS are first class objects that you can interact with. Scheme spec define procedure (interactive-environment) LIPS add also (current-environment).

(let ((x 10))
diff --git a/docs/lips/extension.html b/docs/lips/extension.html
index 410d5939..4f166458 100644
--- a/docs/lips/extension.html
+++ b/docs/lips/extension.html
@@ -4,11 +4,11 @@
 
 
 Extending LIPS | LIPS Scheme
-
+
 
 
 
-

Extending LIPS

+

Extending LIPS

There are two ways to extend LIPS Scheme, one is through macros and the other ways is with syntax extensions.

Macros

diff --git a/docs/lips/functional-helpers.html b/docs/lips/functional-helpers.html index 239e5f95..ad65e409 100644 --- a/docs/lips/functional-helpers.html +++ b/docs/lips/functional-helpers.html @@ -4,11 +4,11 @@ Functional and other utils | LIPS Scheme - + -

Functional and other utils

+

Functional and other utils

LIPS Scheme provide various of utility functions. Some of them are inspired by Ramda.js library and Lodash. Some of those functions are defined in SRFI-1.

diff --git a/docs/lips/intro.html b/docs/lips/intro.html index 2a6bb03a..7f26b5c0 100644 --- a/docs/lips/intro.html +++ b/docs/lips/intro.html @@ -4,11 +4,11 @@ Core features | LIPS Scheme - + -

Core features

+ +version 1.0.

\ No newline at end of file diff --git a/docs/lips/reflection.html b/docs/lips/reflection.html index 908a4d66..170deffe 100644 --- a/docs/lips/reflection.html +++ b/docs/lips/reflection.html @@ -4,11 +4,11 @@ Reflection | LIPS Scheme - + -

Reflection

+

Reflection

You can use standard JavaScript methods to inspect LIPS objects.