Last active
September 22, 2020 04:49
-
-
Save genkuroki/1702e7be9bc41321f0f2f2198b6ed7a3 to your computer and use it in GitHub Desktop.
Minimal Lisp in Julia - Part 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "# Minimal Lisp in Julia - Part 1\n\nGen Kuroki\n\n2020-09-21\n\nReferences:\n\n* [簡易LISP処理系の実装例【各言語版まとめ】](https://qiita.com/ytaki0801/items/dcb0fe48cbeab30ac40d)\n * [簡易LISP処理系の実装例(Julia版)](https://qiita.com/ytaki0801/items/f902bd81cc8828774911)" | |
}, | |
{ | |
"metadata": { | |
"toc": true | |
}, | |
"cell_type": "markdown", | |
"source": "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#Implementation-example-in-Julia-of-minimal-Lisp\" data-toc-modified-id=\"Implementation-example-in-Julia-of-minimal-Lisp-1\"><span class=\"toc-item-num\">1 </span>Implementation example in Julia of minimal Lisp</a></span></li><li><span><a href=\"#Execution-examples\" data-toc-modified-id=\"Execution-examples-2\"><span class=\"toc-item-num\">2 </span>Execution examples</a></span><ul class=\"toc-item\"><li><span><a href=\"#雑多な例\" data-toc-modified-id=\"雑多な例-2.1\"><span class=\"toc-item-num\">2.1 </span>雑多な例</a></span></li><li><span><a href=\"#4つの例\" data-toc-modified-id=\"4つの例-2.2\"><span class=\"toc-item-num\">2.2 </span>4つの例</a></span></li></ul></li><li><span><a href=\"#Juliaにおける類似のコード\" data-toc-modified-id=\"Juliaにおける類似のコード-3\"><span class=\"toc-item-num\">3 </span>Juliaにおける類似のコード</a></span><ul class=\"toc-item\"><li><span><a href=\"#example-1\" data-toc-modified-id=\"example-1-3.1\"><span class=\"toc-item-num\">3.1 </span>example 1</a></span></li><li><span><a href=\"#example2\" data-toc-modified-id=\"example2-3.2\"><span class=\"toc-item-num\">3.2 </span>example2</a></span></li><li><span><a href=\"#example3\" data-toc-modified-id=\"example3-3.3\"><span class=\"toc-item-num\">3.3 </span>example3</a></span></li><li><span><a href=\"#example-4\" data-toc-modified-id=\"example-4-3.4\"><span class=\"toc-item-num\">3.4 </span>example 4</a></span></li></ul></li></ul></div>" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "VERSION", | |
"execution_count": 1, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 1, | |
"data": { | |
"text/plain": "v\"1.6.0-DEV.928\"" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "## Implementation example in Julia of minimal Lisp" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "struct Nil end\nconst nil = Nil()\nBase.show(io::IO, ::Nil) = print(io, \"nil\")\n\nstruct T end\nconst t = T()\nBase.show(io::IO, ::T) = print(io, \"t\")\n\n_tnil(x::Bool) = ifelse(x, t, nil) # true -> t, false -> nil\n\n# Lisp functions in Julia\n\n_eq(x, y) = x == y # eq for Julia\neq(x, y) = _tnil(_eq(x, y)) # eq for Lisp\n\n_null(x) = _eq(x, nil) # null for Julia\nnull(x) = _tnil(_null(x)) # null for Lisp\n\n_atom(x) = true\n_atom(x::Tuple) = false # atom for Julia\natom(x) = _tnil(_atom(x)) # atom for Lisp\n\ncons(x, y) = (x, y)\ncons(x, y::Tuple) = (x, y...)\n\ncar(x) = nil\ncar(x::Tuple) = x[1]\ncdr(x) = nil\nfunction cdr(x::Tuple)\n @assert length(x) != 1 \"The argument of cdr is not an S-expression.\"\n length(x) == 2 ? x[2] : x[2:end]\nend\n\ncaar(x) = car(car(x))\ncadr(x) = car(cdr(x))\ncdar(x) = cdr(car(x))\ncddr(x) = cdr(cdr(x))\n\nfor (x, y, z) in Iterators.product(fill([:a, :d], 3)...)\n cxyzr = Symbol(:c, x, y, z, :r)\n cxr, cyr, czr = Symbol.(:c, (x, y, z), :r)\n @eval $cxyzr(x) = $cxr($cyr($czr(x)))\nend\n\nquote_(x) = x # quote for Lisp\n\nappend(x, y) = _null(x) ? y : cons(car(x), append(cdr(x), y))\n\nlist(x) = cons(x, nil)\nlist(x, y...) = cons(x, list(y...))\n\npair(x, y) = nil\npair(x::Tuple, y::Tuple) = !_null(x) || !_null(y) ?\n cons(list(car(x), car(y)), pair(cdr(x), cdr(y))) : nil\n\nassoc(x, a) = x # a stands for association list\nassoc(x, a::Tuple) = _eq(caar(a), x) ? cadar(a) : assoc(x, cdr(a))\n\n# eval for Lisp\neval_(x, a=nil) = assoc(x, a) # a stands for symbol-to-value association list\nfunction eval_(sexpr::Tuple, a=nil)\n func, args = car(sexpr), cdr(sexpr)\n if _atom(func)\n _eq(func, :quote) && return quote_(car(args))\n _eq(func, :atom) && return atom(eval_(car(args), a))\n _eq(func, :eq) && return eq(eval_(car(args), a), eval_(cadr(args), a))\n _eq(func, :car) && return car(eval_(car(args), a))\n _eq(func, :cdr) && return cdr(eval_(car(args), a))\n _eq(func, :cons) && return cons(eval_(car(args), a), eval_(cadr(args), a))\n _eq(func, :cond) && return cond(args, a)\n if isa(func, Symbol)\n assocfunc = assoc(func, a)\n assocfunc != func && return eval_(cons(assocfunc, args), a)\n end\n elseif _eq(car(func), :lambda)\n p = pair(cadr(func), eval_list(args, a))\n return eval_(caddr(func), append(p, a))\n end\n error(\"Error: The car \", sprint_sexpr(func), \" of \", sprint_sexpr(sexpr), \" is not callable.\")\nend\n\ncond(args, a=nil) = nil\nfunction cond(args::Tuple, a=nil)\n arg = car(args)\n condition, action = car(arg), cadr(arg)\n _eq(eval_(condition, a), t) && return eval_(action, a)\n cond(cdr(args), a)\nend\n\neval_list(x, a=nil) = x\neval_list(x::Tuple, a=nil) = cons(eval_(car(x), a), eval_list(cdr(x), a))\n\n# Convert String code to S-expression\n\n_tok(code) = split(replace(chomp(code), r\"([()'])\"=>s\" \\1 \"))\n\nfunction _literal(x)\n x == \"nil\" && return nil\n x == \"t\" && return t\n occursin(r\"^[+-]?\\d+$\", x) && return parse(Int, x)\n Symbol(x)\nend\n\nfunction _sexpr!(tok)\n tailtok = pop!(tok)\n if tailtok == Symbol(\")\")\n tailexpr = nil\n while tok[end] != Symbol(\"(\")\n if tok[end] == Symbol(\".\")\n pop!(tok)\n tailexpr = cons(_sexpr!(tok), car(tailexpr))\n else\n tailexpr = cons(_sexpr!(tok), tailexpr)\n end\n end\n pop!(tok)\n else\n tailexpr = tailtok\n end\n if !isempty(tok) && tok[end] == Symbol(\"'\")\n pop!(tok)\n return cons(:quote, cons(tailexpr, nil))\n end\n tailexpr\nend\n_sexpr(code) = _sexpr!(_literal.(_tok(code)))\n\n# Print and execute a code and output the result \n\nsprint_sexpr(x) = string(x)\nsprint_sexpr(x::AbstractString) = \"\\\"\" * string(x) * \"\\\"\"\nsprint_sexpr(x::Symbol) = \":\" * string(x)\nfunction sprint_sexpr(x::Tuple)\n s = \"(\"\n n = length(x)\n for i in 1:n-1\n s *= sprint_sexpr(x[i]) * \" \"\n end\n if !_null(x[n])\n s *= \". \" * sprint_sexpr(x[n]) * \")\"\n else\n s = s[1:end-1] * \")\"\n end\n s\nend\nprint_sexpr(x) = print(sprint_sexpr(x))\n\nfunction lisp(code)\n s = _sexpr(code)\n y = eval_(s)\n # md = \"\"\"```commonlisp\n md = \"\"\"```lisp\n \"\"\" * chomp(code) * \"\"\"\n \\n=> \"\"\" * sprint_sexpr(y) * \"\"\"```\\n\\n\"\"\"\n sleep(0.1)\n display(\"text/markdown\", md)\nend\n\nmacro lisp_str(code) :(lisp($(esc(code)))) end", | |
"execution_count": 2, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 2, | |
"data": { | |
"text/plain": "@lisp_str (macro with 1 method)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "code = \"(cdr (car '((1 (2 3)) 4)))\"", | |
"execution_count": 3, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 3, | |
"data": { | |
"text/plain": "\"(cdr (car '((1 (2 3)) 4)))\"" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "tok = _tok(code)", | |
"execution_count": 4, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 4, | |
"data": { | |
"text/plain": "17-element Vector{SubString{String}}:\n \"(\"\n \"cdr\"\n \"(\"\n \"car\"\n \"'\"\n \"(\"\n \"(\"\n \"1\"\n \"(\"\n \"2\"\n \"3\"\n \")\"\n \")\"\n \"4\"\n \")\"\n \")\"\n \")\"" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "tok = _literal.(tok)", | |
"execution_count": 5, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 5, | |
"data": { | |
"text/plain": "17-element Vector{Any}:\n Symbol(\"(\")\n :cdr\n Symbol(\"(\")\n :car\n Symbol(\"'\")\n Symbol(\"(\")\n Symbol(\"(\")\n 1\n Symbol(\"(\")\n 2\n 3\n Symbol(\")\")\n Symbol(\")\")\n 4\n Symbol(\")\")\n Symbol(\")\")\n Symbol(\")\")" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "s = _sexpr!(tok)", | |
"execution_count": 6, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 6, | |
"data": { | |
"text/plain": "(:cdr, (:car, (:quote, ((1, (2, 3, nil), nil), 4, nil), nil), nil), nil)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "tok", | |
"execution_count": 7, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 7, | |
"data": { | |
"text/plain": "Any[]" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "s = _sexpr(code)", | |
"execution_count": 8, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 8, | |
"data": { | |
"text/plain": "(:cdr, (:car, (:quote, ((1, (2, 3, nil), nil), 4, nil), nil), nil), nil)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "_sexpr(code) |> print_sexpr", | |
"execution_count": 9, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(:cdr (:car (:quote ((1 (2 3)) 4))))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(s)", | |
"execution_count": 10, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 10, | |
"data": { | |
"text/plain": "((2, 3, nil), nil)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(s) |> print_sexpr", | |
"execution_count": 11, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "((2 3))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"'((1 (2 3)) 4)\")) |> print_sexpr", | |
"execution_count": 12, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "((1 (2 3)) 4)", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(car '((1 (2 3)) 4))\")) |> print_sexpr", | |
"execution_count": 13, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(1 (2 3))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true, | |
"scrolled": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(car (car '((1 (2 3)) 4)))\")) |> print_sexpr", | |
"execution_count": 14, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "1", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(cdr (car '((1 (2 3)) 4)))\")) |> print_sexpr", | |
"execution_count": 15, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "((2 3))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(car (cdr (car '((1 (2 3)) 4))))\")) |> print_sexpr", | |
"execution_count": 16, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(2 3)", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(cdr '((1 (2 3)) 4))\")) |> print_sexpr", | |
"execution_count": 17, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(4)", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "eval_(_sexpr(\"(car (cdr '((1 (2 3)) 4)))\")) |> print_sexpr", | |
"execution_count": 18, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "4", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "## Execution examples" | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### 雑多な例" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"nil\"", | |
"execution_count": 19, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\nnil\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"t\"", | |
"execution_count": 20, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\nt\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'-123\"", | |
"execution_count": 21, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n'-123\n=> -123```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'nil\"", | |
"execution_count": 22, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n'nil\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'t\"", | |
"execution_count": 23, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n't\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"scrolled": false, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(1 2 3)\"", | |
"execution_count": 24, | |
"outputs": [ | |
{ | |
"output_type": "error", | |
"ename": "LoadError", | |
"evalue": "Error: The car 1 of (1 2 3) is not callable.", | |
"traceback": [ | |
"Error: The car 1 of (1 2 3) is not callable.", | |
"", | |
"Stacktrace:", | |
" [1] error(::String, ::String, ::String, ::String, ::String)", | |
" @ Base .\\error.jl:42", | |
" [2] eval_(sexpr::Tuple{Int64, Int64, Int64, Nil}, a::Nil)", | |
" @ Main .\\In[2]:79", | |
" [3] eval_(sexpr::Tuple{Int64, Int64, Int64, Nil})", | |
" @ Main .\\In[2]:62", | |
" [4] lisp(code::String)", | |
" @ Main .\\In[2]:150", | |
" [5] top-level scope", | |
" @ In[24]:1", | |
" [6] eval", | |
" @ .\\boot.jl:345 [inlined]", | |
" [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)", | |
" @ Base .\\loading.jl:1019" | |
] | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'(1 2 3)\"", | |
"execution_count": 25, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n'(1 2 3)\n=> (1 2 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(quote (1 2 3))\"", | |
"execution_count": 26, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(quote (1 2 3))\n=> (1 2 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(atom -123)\"", | |
"execution_count": 27, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(atom -123)\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(atom nil)\"", | |
"execution_count": 28, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(atom nil)\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(atom t)\"", | |
"execution_count": 29, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(atom t)\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(atom '(1 2 3))\"", | |
"execution_count": 30, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(atom '(1 2 3))\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"\"\"(eq 2 3)\"\"\"", | |
"execution_count": 31, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(eq 2 3)\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"\"\"(eq 3 3)\"\"\"", | |
"execution_count": 32, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(eq 3 3)\n=> t```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(car '((1 2) (3 4) 5))\"", | |
"execution_count": 33, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(car '((1 2) (3 4) 5))\n=> (1 2)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(car (car '((1 2) (3 4))))\"", | |
"execution_count": 34, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(car (car '((1 2) (3 4))))\n=> 1```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cdr '((1 2) (3 4) 5))\"", | |
"execution_count": 35, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cdr '((1 2) (3 4) 5))\n=> ((3 4) 5)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(car (cdr '((1 2) (3 4) 5)))\"", | |
"execution_count": 36, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(car (cdr '((1 2) (3 4) 5)))\n=> (3 4)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cdr (cdr '((1 2) (3 4) 5)))\"", | |
"execution_count": 37, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cdr (cdr '((1 2) (3 4) 5)))\n=> (5)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cdr (cdr (cdr '((1 2) (3 4) 5))))\"", | |
"execution_count": 38, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cdr (cdr (cdr '((1 2) (3 4) 5))))\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cdr (cdr (cdr (cdr '((1 2) (3 4) 5)))))\"", | |
"execution_count": 39, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cdr (cdr (cdr (cdr '((1 2) (3 4) 5)))))\n=> nil```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cons 1 2)\"", | |
"execution_count": 40, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cons 1 2)\n=> (1 . 2)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cons 1 (cons 2 3))\"", | |
"execution_count": 41, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cons 1 (cons 2 3))\n=> (1 2 . 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'(1 2 3)\"", | |
"execution_count": 42, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n'(1 2 3)\n=> (1 2 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cond ((eq 1 1) a) ((eq 1 2) b) ((eq 1 3) c) (t d))\"", | |
"execution_count": 43, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cond ((eq 1 1) a) ((eq 1 2) b) ((eq 1 3) c) (t d))\n=> :a```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cond ((eq 2 1) a) ((eq 2 2) b) ((eq 2 3) c) (t d))\"", | |
"execution_count": 44, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cond ((eq 2 1) a) ((eq 2 2) b) ((eq 2 3) c) (t d))\n=> :b```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cond ((eq 1 2) a) ((eq 3 2) b) ((eq 3 3) c) (t d))\"", | |
"execution_count": 45, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cond ((eq 1 2) a) ((eq 3 2) b) ((eq 3 3) c) (t d))\n=> :c```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cond ((eq 0 1) a) ((eq 0 2) b) ((eq 0 3) c) (t d))\"", | |
"execution_count": 46, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cond ((eq 0 1) a) ((eq 0 2) b) ((eq 0 3) c) (t d))\n=> :d```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(foo '(1 2 3))\"", | |
"execution_count": 47, | |
"outputs": [ | |
{ | |
"output_type": "error", | |
"ename": "LoadError", | |
"evalue": "Error: The car :foo of (:foo (:quote (1 2 3))) is not callable.", | |
"traceback": [ | |
"Error: The car :foo of (:foo (:quote (1 2 3))) is not callable.", | |
"", | |
"Stacktrace:", | |
" [1] error(::String, ::String, ::String, ::String, ::String)", | |
" @ Base .\\error.jl:42", | |
" [2] eval_(sexpr::Tuple{Symbol, Tuple{Symbol, Tuple{Int64, Int64, Int64, Nil}, Nil}, Nil}, a::Nil)", | |
" @ Main .\\In[2]:79", | |
" [3] eval_(sexpr::Tuple{Symbol, Tuple{Symbol, Tuple{Int64, Int64, Int64, Nil}, Nil}, Nil})", | |
" @ Main .\\In[2]:62", | |
" [4] lisp(code::String)", | |
" @ Main .\\In[2]:150", | |
" [5] top-level scope", | |
" @ In[47]:1", | |
" [6] eval", | |
" @ .\\boot.jl:345 [inlined]", | |
" [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)", | |
" @ Base .\\loading.jl:1019" | |
] | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"(cdr '(1 2 3))\"", | |
"execution_count": 48, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(cdr '(1 2 3))\n=> (2 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"\"\"\n((lambda (f x) (f x)) 'cdr '(1 2 3))\n\"\"\"", | |
"execution_count": 49, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n((lambda (f x) (f x)) 'cdr '(1 2 3))\n=> (2 3)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"((lambda (x y) (car x)) '(1 2) 3)\"", | |
"execution_count": 50, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n((lambda (x y) (car x)) '(1 2) 3)\n=> 1```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"((1 2) . (3 4))\"", | |
"execution_count": 51, | |
"outputs": [ | |
{ | |
"output_type": "error", | |
"ename": "LoadError", | |
"evalue": "Error: The car (1 2) of ((1 2) 3 4) is not callable.", | |
"traceback": [ | |
"Error: The car (1 2) of ((1 2) 3 4) is not callable.", | |
"", | |
"Stacktrace:", | |
" [1] error(::String, ::String, ::String, ::String, ::String)", | |
" @ Base .\\error.jl:42", | |
" [2] eval_(sexpr::Tuple{Tuple{Int64, Int64, Nil}, Int64, Int64, Nil}, a::Nil)", | |
" @ Main .\\In[2]:79", | |
" [3] eval_(sexpr::Tuple{Tuple{Int64, Int64, Nil}, Int64, Int64, Nil})", | |
" @ Main .\\In[2]:62", | |
" [4] lisp(code::String)", | |
" @ Main .\\In[2]:150", | |
" [5] top-level scope", | |
" @ In[51]:1", | |
" [6] eval", | |
" @ .\\boot.jl:345 [inlined]", | |
" [7] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)", | |
" @ Base .\\loading.jl:1019" | |
] | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "lisp\"'((1 2) . (3 4))\"", | |
"execution_count": 52, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n'((1 2) . (3 4))\n=> ((1 2) 3 4)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### 4つの例\n\nThe four examples in https://qiita.com/ytaki0801/items/f902bd81cc8828774911" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "# example 1\nlisp\"(car (cdr '(10 20 30)))\"", | |
"execution_count": 53, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n(car (cdr '(10 20 30)))\n=> 20```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "# example 2\n\nlisp\"((lambda (x) (car (cdr x))) '(abc def ghi))\"", | |
"execution_count": 54, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n((lambda (x) (car (cdr x))) '(abc def ghi))\n=> :def```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "# example 3\n\nlisp\"\"\"\n((lambda (f x y) (f x (f y '())))\n '(lambda (x y) (cons x (cons y '())))\n '10 '20)\n\"\"\"", | |
"execution_count": 55, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n((lambda (f x y) (f x (f y '())))\n '(lambda (x y) (cons x (cons y '())))\n '10 '20)\n=> (10 (20 nil))```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"scrolled": false, | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "# example 4\n\nlisp\"\"\"\n((lambda (assoc k v) (assoc k v))\n '(lambda (k v)\n (cond ((eq v '()) nil)\n ((eq (car (car v)) k)\n (car v))\n ('t (assoc k (cdr v)))))\n 'Orange\n '((Apple . 120) (Orange . 210) (Lemmon . 180)))\n\"\"\"", | |
"execution_count": 56, | |
"outputs": [ | |
{ | |
"output_type": "display_data", | |
"data": { | |
"text/markdown": "```lisp\n((lambda (assoc k v) (assoc k v))\n '(lambda (k v)\n (cond ((eq v '()) nil)\n ((eq (car (car v)) k)\n (car v))\n ('t (assoc k (cdr v)))))\n 'Orange\n '((Apple . 120) (Orange . 210) (Lemmon . 180)))\n=> (:Orange . 210)```\n\n" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "1つ目のlambda式における変数 assoc には2つ目のlambda式が代入され, 2つ目のlambda式におけるassocとして1つ目のlambda式中のassoc が使われる. これによって, recursive call が実現されていることに注意せよ. Juliaで同様の結果を得るためのコードが次の節にある." | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "## Juliaにおける類似のコード\n\n直上の例は `assoc` の名前が有効な範囲が「広い」ことを巧妙に利用している.\n\nそれと同じことはJuliaでそのままではできないのだが, 以下のように極めて類似したコードを書くことができる(example4)." | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "このノートの実装では, Lispにおける (1 2 3 4) と (1 2 3 . 4) はJuliaにおけるタプルたち (1, 2, 3, 4, nil) と (1, 2, 3, 4) で実現されていることに注意せよ." | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "_sexpr(\"(1 2 3 4)\")", | |
"execution_count": 57, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 57, | |
"data": { | |
"text/plain": "(1, 2, 3, 4, nil)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "sprint_sexpr((1, 2, 3, 4, nil)) ", | |
"execution_count": 58, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 58, | |
"data": { | |
"text/plain": "\"(1 2 3 4)\"" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "_sexpr(\"(1 2 3 . 4)\")", | |
"execution_count": 59, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 59, | |
"data": { | |
"text/plain": "(1, 2, 3, 4)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "sprint_sexpr((1, 2, 3, 4)) ", | |
"execution_count": 60, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 60, | |
"data": { | |
"text/plain": "\"(1 2 3 . 4)\"" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### example 1\n\n```lisp\n(car (cdr '(10 20 30)))\n=> 20\n```" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "example1 = :(\n car(cdr((10, 20, 30, nil)))\n)\n\neval(example1)", | |
"execution_count": 61, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 61, | |
"data": { | |
"text/plain": "20" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "Meta.show_sexpr(Base.remove_linenums!(example1))", | |
"execution_count": 62, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(:call, :car, (:call, :cdr, (:tuple, 10, 20, 30, :nil)))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "using AbstractTrees\nAbstractTrees.printnode(io::IO, expr::Expr) = show(io, expr.head)\nprint_tree(Base.remove_linenums!(example1), 10)", | |
"execution_count": 63, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": ":call\n├─ :car\n└─ :call\n ├─ :cdr\n └─ :tuple\n ├─ 10\n ├─ 20\n ├─ 30\n └─ :nil\n", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### example2\n\n```lisp\n((lambda (x) (car (cdr x))) '(abc def ghi))\n=> :def\n```\n\nに類似のJuliaのコード:" | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "example2 = :(\n (function (x) car(cdr(x)) end)((:abc, :def, :ghi, nil))\n)\n\neval(example2)", | |
"execution_count": 64, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 64, | |
"data": { | |
"text/plain": ":def" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "Meta.show_sexpr(Base.remove_linenums!(example2))", | |
"execution_count": 65, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(:call, (:function, (:tuple, :x), (:block,\n (:call, :car, (:call, :cdr, :x))\n )), (:tuple, (:quote, #QuoteNode\n :abc\n ), (:quote, #QuoteNode\n :def\n ), (:quote, #QuoteNode\n :ghi\n ), :nil))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "using AbstractTrees\nAbstractTrees.printnode(io::IO, expr::Expr) = show(io, expr.head)\nprint_tree(Base.remove_linenums!(example2), 10)", | |
"execution_count": 66, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": ":call\n├─ :function\n│ ├─ :tuple\n│ │ └─ :x\n│ └─ :block\n│ └─ :call\n│ ├─ :car\n│ └─ :call\n│ ├─ :cdr\n│ └─ :x\n└─ :tuple\n ├─ :(:abc)\n ├─ :(:def)\n ├─ :(:ghi)\n └─ :nil\n", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### example3\n\n```lisp\n((lambda (f x y) (f x (f y '())))\n '(lambda (x y) (cons x (cons y '())))\n '10 '20)\n=> (10 (20 nil))\n```\n\nに類似のJuliaのコードの例." | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "example3 = :(\n (function (f, x, y) f(x, f(y, nil)) end)(\n (function (x, y) cons(x, cons(y, nil)) end),\n 10, 20\n )\n)\n\neval(example3) |> print_sexpr", | |
"execution_count": 67, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(10 (20 nil))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "Meta.show_sexpr(Base.remove_linenums!(example3))", | |
"execution_count": 68, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(:call, (:function, (:tuple, :f, :x, :y), (:block,\n (:call, :f, :x, (:call, :f, :y, :nil))\n )), (:function, (:tuple, :x, :y), (:block,\n (:call, :cons, :x, (:call, :cons, :y, :nil))\n )), 10, 20)", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "using AbstractTrees\nAbstractTrees.printnode(io::IO, expr::Expr) = show(io, expr.head)\nprint_tree(Base.remove_linenums!(example3), 10)", | |
"execution_count": 69, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": ":call\n├─ :function\n│ ├─ :tuple\n│ │ ├─ :f\n│ │ ├─ :x\n│ │ └─ :y\n│ └─ :block\n│ └─ :call\n│ ├─ :f\n│ ├─ :x\n│ └─ :call\n│ ├─ :f\n│ ├─ :y\n│ └─ :nil\n├─ :function\n│ ├─ :tuple\n│ │ ├─ :x\n│ │ └─ :y\n│ └─ :block\n│ └─ :call\n│ ├─ :cons\n│ ├─ :x\n│ └─ :call\n│ ├─ :cons\n│ ├─ :y\n│ └─ :nil\n├─ 10\n└─ 20\n", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": {}, | |
"cell_type": "markdown", | |
"source": "### example 4\n\n```lisp\n((lambda (assoc k v) (assoc k v))\n '(lambda (k v)\n (cond ((eq v '()) nil)\n ((eq (car (car v)) k)\n (car v))\n ('t (assoc k (cdr v)))))\n 'Orange\n '((Apple . 120) (Orange . 210) (Lemmon . 180)))\n=> (:Orange . 210)\n```\n\nに類似のJuliaのコード." | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "example4 = :(\n (\n function (assoc, k, v) assoc(k, v) end\n )(\n (\n function f(k, v)\n if v == ()\n nil\n elseif car(car(v)) == k\n car(v)\n else\n f(k, cdr(v))\n end\n end; f\n ),\n :Orange,\n ((:Apple, 120), (:Orange, 210), (:Lemmon, 180), nil)\n )\n)\n\neval(example4)", | |
"execution_count": 70, | |
"outputs": [ | |
{ | |
"output_type": "execute_result", | |
"execution_count": 70, | |
"data": { | |
"text/plain": "(:Orange, 210)" | |
}, | |
"metadata": {} | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "Meta.show_sexpr(Base.remove_linenums!(copy(example4)))", | |
"execution_count": 71, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": "(:call, (:function, (:tuple, :assoc, :k, :v), (:block,\n (:call, :assoc, :k, :v)\n )), (:block,\n (:function, (:call, :f, :k, :v), (:block,\n (:if, (:call, :(==), :v, (:tuple,)), (:block,\n :nil\n ), (:elseif, (:block,\n (:call, :(==), (:call, :car, (:call, :car, :v)), :k)\n ), (:block,\n (:call, :car, :v)\n ), (:block,\n (:call, :f, :k, (:call, :cdr, :v))\n )))\n )),\n :f\n ), (:quote, #QuoteNode\n :Orange\n ), (:tuple, (:tuple, (:quote, #QuoteNode\n :Apple\n ), 120), (:tuple, (:quote, #QuoteNode\n :Orange\n ), 210), (:tuple, (:quote, #QuoteNode\n :Lemmon\n ), 180), :nil))", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true, | |
"scrolled": false | |
}, | |
"cell_type": "code", | |
"source": "using AbstractTrees\nAbstractTrees.printnode(io::IO, expr::Expr) = show(io, expr.head)\nprint_tree(Base.remove_linenums!(copy(example4)), 10)", | |
"execution_count": 72, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"text": ":call\n├─ :function\n│ ├─ :tuple\n│ │ ├─ :assoc\n│ │ ├─ :k\n│ │ └─ :v\n│ └─ :block\n│ └─ :call\n│ ├─ :assoc\n│ ├─ :k\n│ └─ :v\n├─ :block\n│ ├─ :function\n│ │ ├─ :call\n│ │ │ ├─ :f\n│ │ │ ├─ :k\n│ │ │ └─ :v\n│ │ └─ :block\n│ │ └─ :if\n│ │ ├─ :call\n│ │ │ ├─ :(==)\n│ │ │ ├─ :v\n│ │ │ └─ :tuple\n│ │ ├─ :block\n│ │ │ └─ :nil\n│ │ └─ :elseif\n│ │ ├─ :block\n│ │ │ └─ :call\n│ │ │ ├─ :(==)\n│ │ │ ├─ :call\n│ │ │ │ ├─ :car\n│ │ │ │ └─ :call\n│ │ │ │ ├─ :car\n│ │ │ │ └─ :v\n│ │ │ └─ :k\n│ │ ├─ :block\n│ │ │ └─ :call\n│ │ │ ├─ :car\n│ │ │ └─ :v\n│ │ └─ :block\n│ │ └─ :call\n│ │ ├─ :f\n│ │ ├─ :k\n│ │ └─ :call\n│ │ ├─ :cdr\n│ │ └─ :v\n│ └─ :f\n├─ :(:Orange)\n└─ :tuple\n ├─ :tuple\n │ ├─ :(:Apple)\n │ └─ 120\n ├─ :tuple\n │ ├─ :(:Orange)\n │ └─ 210\n ├─ :tuple\n │ ├─ :(:Lemmon)\n │ └─ 180\n └─ :nil\n", | |
"name": "stdout" | |
} | |
] | |
}, | |
{ | |
"metadata": { | |
"trusted": true | |
}, | |
"cell_type": "code", | |
"source": "", | |
"execution_count": null, | |
"outputs": [] | |
} | |
], | |
"metadata": { | |
"@webio": { | |
"lastKernelId": null, | |
"lastCommId": null | |
}, | |
"_draft": { | |
"nbviewer_url": "https://gist.github.com/1702e7be9bc41321f0f2f2198b6ed7a3" | |
}, | |
"gist": { | |
"id": "1702e7be9bc41321f0f2f2198b6ed7a3", | |
"data": { | |
"description": "Minimal Lisp in Julia - Part 1", | |
"public": true | |
} | |
}, | |
"kernelspec": { | |
"name": "julia-1.6-o3-depwarn", | |
"display_name": "Julia 1.6.0-DEV depwarn -O3", | |
"language": "julia" | |
}, | |
"language_info": { | |
"file_extension": ".jl", | |
"name": "julia", | |
"mimetype": "application/julia", | |
"version": "1.6.0" | |
}, | |
"toc": { | |
"nav_menu": {}, | |
"number_sections": true, | |
"sideBar": true, | |
"skip_h1_title": true, | |
"base_numbering": 1, | |
"title_cell": "Table of Contents", | |
"title_sidebar": "Contents", | |
"toc_cell": true, | |
"toc_position": {}, | |
"toc_section_display": true, | |
"toc_window_display": false | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment