{"id":18447072,"url":"https://github.com/zot/lazp","last_synced_at":"2025-04-15T02:45:59.828Z","repository":{"id":2818332,"uuid":"3820068","full_name":"zot/Lazp","owner":"zot","description":"This has changed to Lisure -- see the Liesure repository: http://github.com/zot/Leisure","archived":false,"fork":false,"pushed_at":"2012-04-17T19:01:19.000Z","size":2000,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-15T02:45:55.652Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://github.com/zot/Leisure","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zot.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-03-24T20:48:31.000Z","updated_at":"2014-10-11T19:28:29.000Z","dependencies_parsed_at":"2022-08-26T18:00:10.648Z","dependency_job_id":null,"html_url":"https://github.com/zot/Lazp","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zot%2FLazp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zot%2FLazp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zot%2FLazp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zot%2FLazp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zot","download_url":"https://codeload.github.com/zot/Lazp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248997087,"owners_count":21195797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T07:11:52.948Z","updated_at":"2025-04-15T02:45:59.811Z","avatar_url":"https://github.com/zot.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e\n\u003c!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\t\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"\u003e\n\n\u003chtml xmlns=\"http://www.w3.org/1999/xhtml\"\u003e\n\n\u003chead\u003e\n\u003ctitle\u003eREADME.md\u003c/title\u003e\n\n\u003c/head\u003e\n\n\u003cbody\u003e\n\n\u003cp\u003e\u003ca href=\"README.html\"\u003eMain\u003c/a\u003e \u003ca href=\"REFERENCE.html\"\u003eReference\u003c/a\u003e \u003ca href=\"TODO.html\"\u003eStatus\u003c/a\u003e \u003ca href=\"http://github.com/zot/Leisure\"\u003eSource\u003c/a\u003e \u003ca href=\"leisure.html\"\u003eREPL\u003c/a\u003e \u003ca href=\"std.lsr\"\u003eStandard functions\u003c/a\u003e\u003c/p\u003e\n\n\u003ch1\u003ePlease Note: the repository is now \u003ca href=\"http://github.com/zot/Leisure\"\u003ehttp://github.com/zot/Leisure\u003c/a\u003e\u003c/h1\u003e\n\n\u003ch1\u003eLeisure: a convenient, untyped, lazy Lambda Calculus with Metaprogramming and Primitives\u003c/h1\u003e\n\n\u003cp\u003eThe goal, here is to provide a convenient language people's use and experimentation that people can easily tailor to their own needs.\u003c/p\u003e\n\n\u003ch2\u003eConvenient\u003c/h2\u003e\n\n\u003cp\u003eLeisure provides a convenient syntax and powerful tools to help people try things out quickly and be productive.  Leisure's syntax is based on Lambda Calculus and borrows things from Haskell and other languages while still remaining a very small language.\u003c/p\u003e\n\n\u003ch3\u003eLambdas\u003c/h3\u003e\n\n\u003cp\u003eAs in Haskell, you can write lambda either as 𝛌 or .  Lambdas are structured as: \u003cstrong\u003e𝛌 variable . body\u003c/strong\u003e and if you provide serveral space-separated variables, Leisure automatically constructs nested lambdas for you, like this: \u003cstrong\u003e\\a b . a\u003c/strong\u003e\u003c/p\u003e\n\n\u003ch3\u003eFunction definitions\u003c/h3\u003e\n\n\u003cp\u003eYou define a function with a declaration, an '=', and a body, like this: \u003cstrong\u003etrue = \\a b . a\u003c/strong\u003e.  You maplace arguments before the '=' and omit the '\\' and '.', like this: \u003cstrong\u003etrue a b = a\u003c/strong\u003e.\u003c/p\u003e\n\n\u003cp\u003eLeisure allows some simplistic parser tweaks; you can define tokens, so you can leave out spaces, and you can define tokens that open and close groups.\u003c/p\u003e\n\n\u003ch3\u003eCurly braces\u003c/h3\u003e\n\n\u003cp\u003eCurly braces produce in-line groups, separated by semicolons, so instead of \u003cstrong\u003e(a (b c) (d e f) g)\u003c/strong\u003e, you could say: \u003cstrong\u003ea {b c; d e f} g\u003c/strong\u003e (or \u003cstrong\u003e{a;b c;d e f;g}\u003c/strong\u003e, etc.).\u003c/p\u003e\n\n\u003ch3\u003eIndentation\u003c/h3\u003e\n\n\u003cp\u003eLeisure supports Python-style indentation, which it replaces with curly braces and semicolons during parsing.  Indented lines are considered to be part of the preceding overhanging line and each indented line produces a parenthesized group, so this:\u003c/p\u003e\n\n\u003cpre\u003e\u003cb\u003e\u003cbig\u003e\ndo  \n  n \u003c- prompt \"What is your name? \"  \n  a \u003c- prompt (concat [\"Hello, \", n, \", thank you for joining us.  How old are you?\"])\n  seconds = * a 31536000\n  print (concat [\"You have been alive more than \", seconds, \" seconds.\"])\n\u003c/big\u003e\u003c/b\u003e\u003c/pre\u003e\n\n\u003cp\u003eis equivalent to this: \u003cstrong\u003edo {n \u0026lt;- prompt \"What is your name? \"; print (concat [\"Hello, \", n, \", thank you for joining us.\"])}\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eand this:\u003c/p\u003e\n\n\u003cpre\u003e\u003cb\u003e\u003cbig\u003e\nlet\n  a = 3\n  b = + a 1\n  a = * a b\n  [a, b]\n\u003c/big\u003e\u003c/b\u003e\u003c/pre\u003e\n\n\u003cp\u003eis equivalent to this: \u003cstrong\u003elet {a \u0026lt;- 3; b \u0026lt;- + a 1; a \u0026lt;- * a b; [a, b]}\u003c/strong\u003e\u003c/p\u003e\n\n\u003ch2\u003eUntyped\u003c/h2\u003e\n\n\u003cp\u003eLeisure is untyped.  This doesn't mean that Leisure is type-free, it just means that variables don't have types -- they can hold anything.  Leisure does have data types -- e.g. you can tell if something is a cons-cell (\u003cstrong\u003e_is (cons 1 nil) cons\u003c/strong\u003e returns \u003cstrong\u003etrue\u003c/strong\u003e).  Whenever you define a function that returns a lambda, it marks instances of that lambda as having the type of the definition.  For example, if you say:\u003c/p\u003e\n\n\u003cp\u003e\u003cstrong\u003eperson name addr = \\f . f name addr\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eThen \u003cstrong\u003e(is (person a b) person)\u003c/strong\u003e will return \u003cstrong\u003etrue\u003c/strong\u003e and \u003cstrong\u003e(getType (person a b))\u003c/strong\u003e will return \u003cstrong\u003esome person\u003c/strong\u003e (an option).  \u003cstrong\u003e(getType \\x . x)\u003c/strong\u003e, however, will return none, because naked lambdas have no type (at this point, anyway).\u003c/p\u003e\n\n\u003ch2\u003eLazy\u003c/h2\u003e\n\n\u003cp\u003eLeisure is lazy.  It doesn't allow side effects, not because side effects are somehow \u003cem\u003eevil\u003c/em\u003e, but because in a lazy language, side effects can lead to very strange behavior that's very hard to diagnose.  The idea is to have side effects outside the Leisure environment and access them using standard functional techniques, like monads and FRP.\u003c/p\u003e\n\n\u003ch2\u003eMetaprogramming\u003c/h2\u003e\n\n\u003cp\u003eLeisure provides several tools for metaprogramming:\u003c/p\u003e\n\n\u003cp\u003eFunctions\n* getType data -- returns an option with the type of the data (or none if it has no type)\n* is data type -- returns a boolean indicating whether data is of the type\n* eq a b -- returns a boolean indicating whether a and b are identically equal\n* parse string -- returns an AST for the string\n* eval AST -- evaluates ast\u003c/p\u003e\n\n\u003cp\u003eMacros\n* declaration =M= definition -- declares a macro that runs at parse-time.  Input is the AST for the macro expression and output is a new AST to replace the old one.  Further macro replacement is done on the result.  The identity macro is: \u003cstrong\u003eidentMacro ast =M= ast\u003c/strong\u003e.\n* Do and let are macros\n   * let uses = to assign (and reassign) variables and returns the result of an expression using those variables\n   * do uses = like let and uses \u0026lt;- to bind monads\u003c/p\u003e\n\n\u003ch2\u003eAST Function usage\u003c/h2\u003e\n\n\u003cp\u003elit v -- a literal value \u003cbr /\u003e\nref v -- a variable reference: v should be a string \u003cbr /\u003e\nlambda var body -- a lambda: var should be a string or number, body is an AST \u003cbr /\u003e\napply func arg -- a function application: func can be any AST function except a _prim  \u003c/p\u003e\n\n\u003ch2\u003eAST Function definitions\u003c/h2\u003e\n\n\u003cp\u003elit x = \\f . f x \u003cbr /\u003e\nref x = \\f . f x \u003cbr /\u003e\nlambda v f = \\g . g v f \u003cbr /\u003e\napply func arg = \\f . f func arg  \u003c/p\u003e\n\n\u003ch2\u003eRunning it\u003c/h2\u003e\n\n\u003ch3\u003eRunning the REPL\u003c/h3\u003e\n\n\u003cblockquote\u003e\n  \u003cp\u003enode runRepl\nRuns the read eval print loop.  You can enter Leisure expressions and definitions there.\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003ch3\u003eCompiling files\u003c/h3\u003e\n\n\u003cblockquote\u003e\n  \u003cp\u003enode runRepl -c file1 file2 ...\nCompiles files.  \u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003ch3\u003eRunning the tests\u003c/h3\u003e\n\n\u003cp\u003eTo run the tests, you can cd into the top level directory and type\u003c/p\u003e\n\n\u003cblockquote\u003e\n  \u003cp\u003enode testLeisure\nIt should give you something like this:\nRunning Tests...\n...\nDone\nSucceeded all 38 tests.\nEach . on the second line represents a successfully completed test.  If there are errors, it will tell you which tests failed.\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003ch2\u003eChanging it\u003c/h2\u003e\n\n\u003cp\u003eIf you want to change things, you'll probably want to change the Coffeescript files, rather than their corresponding javascript versions.  The \u003ca href=\"build\"\u003ebuild\u003c/a\u003e file that contains a command to rebuild it, which is just\u003c/p\u003e\n\n\u003cblockquote\u003e\n  \u003cp\u003enode_modules/coffee-script/bin/coffee -c leisure.cs repl.cs runRepl.cs\u003c/p\u003e\n\u003c/blockquote\u003e\n\n\u003ch2\u003eImplementation\u003c/h2\u003e\n\n\u003cp\u003eLeisure is written in JavaScript and runs in node or in browsers.  Later, Leisure may generate native code, using, for instance, C and/or LLVM.  An LLVM version could use the VMKit’s garbage collector or the Boehm-Demers-Weiser garbage collector, which performs well with small objects (like function contexts).\u003c/p\u003e\n\n\u003c/body\u003e\n\u003c/html\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzot%2Flazp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzot%2Flazp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzot%2Flazp/lists"}