Thun/docs/with_sympy.ipynb

1874 lines
61 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Symbolic Evaluation with SymPy"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import sympy\n",
"\n",
"from joy.joy import run\n",
"from joy.library import UnaryBuiltinWrapper\n",
"from joy.utils.pretty_print import TracePrinter\n",
"from joy.utils.stack import list_to_stack\n",
"\n",
"from notebook_preamble import D, J, V, define"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"sympy.init_printing()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## [SypPy Symbols](http://docs.sympy.org/latest/modules/core.html#module-sympy.core.symbol)\n",
"\n",
"The SymPy package provides a powerful and elegant [\"thunk\"](https://en.wikipedia.org/wiki/Thunk) object that can take the place of a numeric value in calculations and \"record\" the operations performed on it.\n",
"\n",
"We can create some of these objects and put them on the Joy stack:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"stack = list_to_stack(sympy.symbols('c a b'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we evaluate the `quadratic` program\n",
"\n",
" over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
"\n",
"The [SypPy Symbols](http://docs.sympy.org/latest/modules/core.html#module-sympy.core.symbol) will become the symbolic expression of the math operations. Unfortunately, the library `sqrt` function doesn't work with the SymPy objects:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"can't convert expression to float\n",
" b a c . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
" b a c a . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2\n",
"b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2\n",
" b a c . [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2\n",
" b a c [[neg] dupdip sqr 4] . dipd * * - sqrt pm a 2 * [/] cons app2\n",
" b . [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" b [neg] . dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" b . neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b . b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b . sqr 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b . dup mul 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b b . mul 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 . 4 a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 4 . a c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 4 a . c * * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 4 a c . * * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 4 a*c . * - sqrt pm a 2 * [/] cons app2\n",
" -b b**2 4*a*c . - sqrt pm a 2 * [/] cons app2\n",
" -b -4*a*c + b**2 . sqrt pm a 2 * [/] cons app2\n"
]
}
],
"source": [
"viewer = TracePrinter()\n",
"try:\n",
" run('over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2', stack, D, viewer.viewer)\n",
"except Exception, e:\n",
" print e\n",
"viewer.print_()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can pick out that first symbolic expression obect from the Joy stack:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"S, E = viewer.history[-1]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAGUAAAAWCAYAAADZylKgAAAABHNCSVQICAgIfAhkiAAAA3NJREFUaIHt2GuIVVUUB/CfpWU1wlRYTSFDEUHQ5IxCURBMI9EDouhDH3rYNYSgQII+9ADh4oeIpJoi+iAUlUUFlZEETQ0ZvSw1TaJIU5kgMppeGFFWNn1Y+zKn47l35p6544jcP2wOZ+291v6fu/Z67EsbbbQB7sVm7MMo1uO8GWXUhiEsE47owTp8j5NmktSRhtsxhltL6nfgAK6Go1pEqh5uFmTHsHya95pJLErPT0vqzxO++Lk1dOpjAX7Fb458p2zDH5hdUv+lZOPoljEqwCwMYzdWO7ydUhH8+kvqH4u/8ElJ/dXYi7NrgulKXyswIIrZ75NYfwOex04RWb+I7mRZA51+ccK+xX7xYUO4tizpkujBHJG6evEKfhLf/ZbGXdVDWIol2FUTTodTzsUDeBTvTWL9PDyDs/A+HserOBNP4e4CnUFsEI4fxsPpfTEunhr9prE4PbvxoYi6J7EVl+EddBboPYabcCm+nE6Cs7EFO3BcklU1Tl8dOK1A3iWi5quc/P5k72WcUGCru0nOFVNLX2uS/o/oy809m+buy8mfEHeUAfHttdFRkkNDrBKt3UUZWVX5mrIDP2Te+5L9zTimHMWDUDE1p2xRvx2+MM29kJOP1RnVog1GGigUjecyuhfgHzyYs1nV2CknYiU+FrXkQG6PrZm1a5NsSR1bE2GkwbcUjacnsDdH1LMRxZ1Xd7KzrhmSeUO78WcT+t9l7KwVhXplE/rni2J4KjbhRdGr/y1qylJsz6y/XDhuQxN7ZDHo4Pzei2tEXRvJzX02gb0eEbHrxYHMo5ZKv2mKZYvQafKnbzCjt10cgv4Cm6vS+jvS+9z0vq3F3CvKp6/lSfeuOvOPpPmrmjFa9rKTx37RcRRhkagFH4gasTHJF4hIGcK7OZ1O4+1w7ZY8Kz1PmTrdlqHWeRX9Z9WF2/C1yAaHFaqKa8r8JN8pcnMNJwtHjYk0Njcz93mSX1+wzznK3YgrykfKpqS7x/87wQ68LerjFc0abVWklMGo6OEHxG14WJyuK0XN+Ff079kadw9eF7XnFnwhoqpXRF7XIeJO/HY9Ip0eL+rPa+KGfx1Ox5148xBymjSq6ndf80UvPyruJB+J4t5n/BKWxyV4w3hDsFekhxtL8qsoFykLk94anCEuvPvSGCphr4022mijjTZajv8AHtTyPwIcKPQAAAAASUVORK5CYII=\n",
"text/latex": [
"$$- 4 a c + b^{2}$$"
],
"text/plain": [
" 2\n",
"-4⋅a⋅c + b "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q = S[0]\n",
"q"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Python `math.sqrt()` function causes the \"can't convert expression to float\" exception but `sympy.sqrt()` does not:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAHoAAAAdCAYAAABlqHgGAAAABHNCSVQICAgIfAhkiAAABGhJREFUaIHt2muIVVUUwPGfpqU1ghVWFpMUJJVZPnpgUExK9AAthPrQQ8cQgoIIMnqANPghelBalIRgL3tCmSVBlmVU9lDTLHpoD6aIpKwMQ0pKpw/rDF6v597uOffMVeT84XDn7L3X2uucvfdaa+8zlJSU7D/0yyk3FFuKNKRk32Q6LtvbRpT0Pc9gyN42oqRx+ueQOTC5/izYlpI+JM9AT8TbBdtRsg/yMI7d20aUZCPPim7HD0UbUpKJ27AaW7EZS3FKPYGsAz0Wn+QyraRIOjAfZ4tQ+i+W47CiOrgDZxSlrARchx5c04SONuzA5FoNsq7o8VjThEFZuVq8hB7MbGG/rWRc8vtxEzqGiLH8vXlzOAaPFKGoQdrxh9jG7c8DvQ5/YUATOp5P9BxQq0Haiq61yieLoN8K+uEx/Ka1kysPnWIiduSQPQij8KmIs3m4F+eKk8odtRpVD+pkfJlSDpPwZk5jsnKDSDJmYFsD7a/A09goPMAWkZXOqCPTIVbCj9iOTViGS/ManYPRGCjc9hi8KCb3NrzufzJp3IdpYmy+qdewckBPFw9/gsjmKjlEzJa/G7G+SU7CXXgA7zTQfgiewPF4Fw9hMY7Do7glRWYeVojJtBz3J/fj7fnsfcn45HcEVgrPsBBrcT7eEh+Q0ngQV+E8fJGn85W4p6psquaywkYZIJK9DRiclHWpH6PbcFRK+XCxur+qKr8z0feCmMDVukZktLlTfte9IJH9VWxdK3kyqbs9RW6+2ENPFM/ee7Vl6fxm8aIrWYgjsijJyRzhOSZUlHXJn4xtwC8V92MT/avFeX0RdMo/0GvU3lqdldQ9m1LXU+PqytL5yEToxOS+P5Y0INddx4C066kq+TNFQlLtTbrUH+hDMRsfiti8o6qftRVtFyVlkxp4njS6ZXvGx+voGihyg27pGfeIRMdLOW3djbQONoqVMEW4vQn4qAFd38oWw3+qsmNR0vfsDDpOFUnLkViF58Re8h8Ro6dhfUX7C8RkWJGhj0rm2TNmjsElIk/orqqrd4o4WniVpdIz7t4Q8n1mKzNwt4jVvX+P6svOxMtrdJXMq5BbLyZXR4rOOUn765P7Qcn9uoJt75TPdc9M5G6qUT83qb84r2GV1Nqkv4xZIi6fjM+L6KwO20UekMY4EVvfE57mg6S8XazoZfb8bDrUrq1V74lT779NtSLXaITejDvtfHo4rsXXwmP1Gf3xs8hQ5/ZlRw3QJT1GD0vKN4p418vhYvB7hAsfVFH3WVJ+eUo/I9U5WapDp3wrelUi953ds/82vCFyjQtz2JNKrRW9U8SOWUV2VjCbxT5zosghlouVcJGIwTvF/rIyb7gVr4hYPl14qqEizrYn8q1ggIjR63CwiOVLxEnZVByNG/FaK4yZIhKXZs5gi6BL7ax7mNhvbhZ75vdFAjbWrsOHas7Bq3YlbZuEe7wyp32dsq/o0xKZBeIbwmKxL94qvFEWXU0zWHzgLikpKSkpKWk9/wEOzhV2ng+cdgAAAABJRU5ErkJggg==\n",
"text/latex": [
"$$\\sqrt{- 4 a c + b^{2}}$$"
],
"text/plain": [
" _____________\n",
" 2 \n",
"╲╱ -4⋅a⋅c + b "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sympy.sqrt(q)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Use `sympy.sqrt`\n",
"This is easy to fix."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"D['sqrt'] = UnaryBuiltinWrapper(sympy.sqrt)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now it works just fine."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"(root1, (root2, _)) = run('over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2', stack, D)[0]"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/latex": [
"$$\\frac{1}{2 a} \\left(- b - \\sqrt{- 4 a c + b^{2}}\\right)$$"
],
"text/plain": [
" _____________\n",
" 2 \n",
"-b - ╲╱ -4⋅a⋅c + b \n",
"─────────────────────\n",
" 2⋅a "
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"root1"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/latex": [
"$$\\frac{1}{2 a} \\left(- b + \\sqrt{- 4 a c + b^{2}}\\right)$$"
],
"text/plain": [
" _____________\n",
" 2 \n",
"-b + ╲╱ -4⋅a⋅c + b \n",
"─────────────────────\n",
" 2⋅a "
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"root2"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"At some point I will probably make an optional library of Joy wrappers for SymPy functions, and either load it automatically if SymPy installation is available or have a CLI switch or something. There's a huge amount of incredibly useful stuff and I don't see why Joy shouldn't expose another interface for using it. (As an example, the symbolic expressions can be \"lambdafied\" into very fast versions, i.e. a function that takes `a`, `b`, and `c` and computes the value of the root using just low-level fast code, bypassing Joy and Python. Also, Numpy, &c.)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Partial Evaluation\n",
"\n",
"[Futamura projections](https://en.wikipedia.org/wiki/Futamura_projection)\n",
"\n",
"Starting with the example from [Partial Computation of Programs](http://hdl.handle.net/2433/103401)\n",
"by [Yoshihiko Futamura](http://fi.ftmr.info/) of a function to compute `u` to the `k`th power:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"def F(u, k):\n",
" z = 1\n",
" while k != 0:\n",
" if odd(k):\n",
" z = z * u\n",
" k = k / 2\n",
" u = u * u\n",
" return z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Partial evaluation with `k = 5`:"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"def F5(u):\n",
" z = 1 * u\n",
" u = u * u\n",
" u = u * u\n",
" z = z * u\n",
" return z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Translate `F(u, k)` to Joy\n",
"\n",
" u k 1 # z = 1\n",
" [pop] [Fw] while # the while statement\n",
" popopd # discard u k, \"return\" z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"What's Fw?\n",
"\n",
"\n",
" u k z [pop odd] [Ft] [] ifte # the if statement\n",
" [2 //] dip # k = k / 2 floordiv\n",
" [sqr] dipd # u = u * u\n",
"\n",
" [[sqr] dip 2 //] dip # We can merge last two lines."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Helper function Ft (to compute z = z * u).\n",
"\n",
"\n",
" u k z Ft\n",
" ---------------\n",
" u k u*z\n",
"\n",
"\n",
" Ft == [over] dip *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Putting it together:\n",
"\n",
" Ft == [over] dip *\n",
" Fb == [[sqr] dip 2 //] dip\n",
" Fw == [pop odd] [Ft] [] ifte Fb\n",
" F == 1 [pop] [Fw] while popopd"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"define('odd == 2 %')"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
"define('Ft == [over] dip *')"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"define('Fb == [[sqr] dip 2 //] dip')"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"define('Fw == [pop odd] [Ft] [] ifte Fb')"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"define('F == 1 [pop] [Fw] while popopd')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Try it out:"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"32\n"
]
}
],
"source": [
"J('2 5 F')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In order to elide the tests let's define special versions of `while` and `ifte`:"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [
"from joy.joy import joy\n",
"from joy.library import FunctionWrapper\n",
"from joy.parser import Symbol\n",
"from joy.utils.stack import concat\n",
"\n",
"\n",
"S_while = Symbol('while')\n",
"\n",
"\n",
"@FunctionWrapper\n",
"def while_(S, expression, dictionary):\n",
" '''[if] [body] while'''\n",
" (body, (if_, stack)) = S\n",
" if joy(stack, if_, dictionary)[0][0]:\n",
" expression = concat(body, (if_, (body, (S_while, expression))))\n",
" return stack, expression, dictionary\n",
"\n",
"\n",
"@FunctionWrapper\n",
"def ifte(stack, expression, dictionary):\n",
" '''[if] [then] [else] ifte'''\n",
" (else_, (then, (if_, stack))) = stack\n",
" if_res = joy(stack, if_, dictionary)[0][0]\n",
" quote = then if if_res else else_\n",
" expression = concat(quote, expression)\n",
" return (stack, expression, dictionary)\n",
"\n",
"\n",
"D['ifte'] = ifte\n",
"D['while'] = while_"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And with a SymPy symbol for the `u` argument:"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" u 5 . F\n",
" u 5 . 1 [pop] [Fw] while popopd\n",
" u 5 1 . [pop] [Fw] while popopd\n",
" u 5 1 [pop] . [Fw] while popopd\n",
" u 5 1 [pop] [Fw] . while popopd\n",
" u 5 1 . Fw [pop] [Fw] while popopd\n",
" u 5 1 . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 . Ft Fb [pop] [Fw] while popopd\n",
" u 5 1 . [over] dip * Fb [pop] [Fw] while popopd\n",
" u 5 1 [over] . dip * Fb [pop] [Fw] while popopd\n",
" u 5 . over 1 * Fb [pop] [Fw] while popopd\n",
" u 5 u . 1 * Fb [pop] [Fw] while popopd\n",
" u 5 u 1 . * Fb [pop] [Fw] while popopd\n",
" u 5 u . Fb [pop] [Fw] while popopd\n",
" u 5 u . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
" u 5 u [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" u 5 . [sqr] dip 2 // u [pop] [Fw] while popopd\n",
" u 5 [sqr] . dip 2 // u [pop] [Fw] while popopd\n",
" u . sqr 5 2 // u [pop] [Fw] while popopd\n",
" u . dup mul 5 2 // u [pop] [Fw] while popopd\n",
" u u . mul 5 2 // u [pop] [Fw] while popopd\n",
" u**2 . 5 2 // u [pop] [Fw] while popopd\n",
" u**2 5 . 2 // u [pop] [Fw] while popopd\n",
" u**2 5 2 . // u [pop] [Fw] while popopd\n",
" u**2 2 . u [pop] [Fw] while popopd\n",
" u**2 2 u . [pop] [Fw] while popopd\n",
" u**2 2 u [pop] . [Fw] while popopd\n",
" u**2 2 u [pop] [Fw] . while popopd\n",
" u**2 2 u . Fw [pop] [Fw] while popopd\n",
" u**2 2 u . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u**2 2 u [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u**2 2 u [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" u**2 2 u [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" u**2 2 u . Fb [pop] [Fw] while popopd\n",
" u**2 2 u . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
" u**2 2 u [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" u**2 2 . [sqr] dip 2 // u [pop] [Fw] while popopd\n",
" u**2 2 [sqr] . dip 2 // u [pop] [Fw] while popopd\n",
" u**2 . sqr 2 2 // u [pop] [Fw] while popopd\n",
" u**2 . dup mul 2 2 // u [pop] [Fw] while popopd\n",
" u**2 u**2 . mul 2 2 // u [pop] [Fw] while popopd\n",
" u**4 . 2 2 // u [pop] [Fw] while popopd\n",
" u**4 2 . 2 // u [pop] [Fw] while popopd\n",
" u**4 2 2 . // u [pop] [Fw] while popopd\n",
" u**4 1 . u [pop] [Fw] while popopd\n",
" u**4 1 u . [pop] [Fw] while popopd\n",
" u**4 1 u [pop] . [Fw] while popopd\n",
" u**4 1 u [pop] [Fw] . while popopd\n",
" u**4 1 u . Fw [pop] [Fw] while popopd\n",
" u**4 1 u . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u**4 1 u [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u**4 1 u [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" u**4 1 u [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" u**4 1 u . Ft Fb [pop] [Fw] while popopd\n",
" u**4 1 u . [over] dip * Fb [pop] [Fw] while popopd\n",
" u**4 1 u [over] . dip * Fb [pop] [Fw] while popopd\n",
" u**4 1 . over u * Fb [pop] [Fw] while popopd\n",
" u**4 1 u**4 . u * Fb [pop] [Fw] while popopd\n",
" u**4 1 u**4 u . * Fb [pop] [Fw] while popopd\n",
" u**4 1 u**5 . Fb [pop] [Fw] while popopd\n",
" u**4 1 u**5 . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
"u**4 1 u**5 [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" u**4 1 . [sqr] dip 2 // u**5 [pop] [Fw] while popopd\n",
" u**4 1 [sqr] . dip 2 // u**5 [pop] [Fw] while popopd\n",
" u**4 . sqr 1 2 // u**5 [pop] [Fw] while popopd\n",
" u**4 . dup mul 1 2 // u**5 [pop] [Fw] while popopd\n",
" u**4 u**4 . mul 1 2 // u**5 [pop] [Fw] while popopd\n",
" u**8 . 1 2 // u**5 [pop] [Fw] while popopd\n",
" u**8 1 . 2 // u**5 [pop] [Fw] while popopd\n",
" u**8 1 2 . // u**5 [pop] [Fw] while popopd\n",
" u**8 0 . u**5 [pop] [Fw] while popopd\n",
" u**8 0 u**5 . [pop] [Fw] while popopd\n",
" u**8 0 u**5 [pop] . [Fw] while popopd\n",
" u**8 0 u**5 [pop] [Fw] . while popopd\n",
" u**8 0 u**5 . popopd\n",
" u**5 . \n"
]
}
],
"source": [
"stack = list_to_stack([5, sympy.symbols('u')])\n",
"viewer = TracePrinter()\n",
"try:\n",
" (result, _) = run('F', stack, D, viewer.viewer)[0]\n",
"except Exception, e:\n",
" print e\n",
"viewer.print_()"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAWCAYAAADafVyIAAAABHNCSVQICAgIfAhkiAAAAUpJREFUSInt1DtLXUEUBeBPESLXFGITsDEqEdHKaLBMQBvFRsh/SG9nKouAjY0/IsQm2lgoNrENeaEgaKGVjyBaBLQQNRYzSYbjOVduzoWkcMGwmb1n1pr9YPjPMYOfmXWUHmiqg8g2XiT7q3oLXMq8OkVjHQS6sI89vMPjNNhQknwMFezgEabRh36cluTORQu+Y+qXI1ui18IkTOZc7oixxSoCZ9jCkyKBp9F+zrk8FO3XKgLN6MVh0YE9HBfEZoUMJhLfHJ6jE8NYxg8h21toiwQrBQJrMd6e+BZwgAthkt4LTc7FaCR4UxA/ERpYE9IeDEabV/8uIcMvZQQGos0jGY+2WoPvxDehllk8wKZQvpdlBD5Gkp7E14K3/vyU3bWSpp/dKp5hHUt4iBFsCHNdwe5fPPw3mjEvjN05PuEVWnGND2XI7/HvcAOaJEK/e6V+UwAAAABJRU5ErkJggg==\n",
"text/latex": [
"$$u^{5}$$"
],
"text/plain": [
" 5\n",
"u "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's try partial evaluation by hand and use a \"stronger\" thunk.\n",
"\n",
"Caret underscoring indicates terms that form thunks. When an arg is unavailable for a computation we just postpone it until the arg becomes available and in the meantime treat the pending computation as one unit.\n",
"\n",
" u 5 . F\n",
" u 5 . 1 [pop] [Fw] while popopd\n",
" u 5 1 . [pop] [Fw] while popopd\n",
" u 5 1 [pop] . [Fw] while popopd\n",
" u 5 1 [pop] [Fw] . while popopd\n",
" u 5 1 . Fw [pop] [Fw] while popopd\n",
" u 5 1 . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" u 5 1 . Ft Fb [pop] [Fw] while popopd\n",
" u 5 1 . [over] dip * Fb [pop] [Fw] while popopd\n",
" u 5 1 [over] . dip * Fb [pop] [Fw] while popopd\n",
" u 5 . over 1 * Fb [pop] [Fw] while popopd\n",
" u 5 u . 1 * Fb [pop] [Fw] while popopd\n",
" u 5 u 1 . * Fb [pop] [Fw] while popopd\n",
" u 5 u . Fb [pop] [Fw] while popopd\n",
" u 5 u . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
" u 5 u [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" u 5 . [sqr] dip 2 // u [pop] [Fw] while popopd\n",
" u 5 [sqr] . dip 2 // u [pop] [Fw] while popopd\n",
" u . sqr 5 2 // u [pop] [Fw] while popopd\n",
" u . dup mul 5 2 // u [pop] [Fw] while popopd\n",
" u dup * . 5 2 // u [pop] [Fw] while popopd\n",
" ^^^^^^^"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
" u dup * 2 u [pop] [Fw] . while popopd\n",
" u dup * 2 u . Fw [pop] [Fw] while popopd\n",
" u dup * 2 u . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u dup * 2 u [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" u dup * 2 u [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" u dup * 2 u [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" u dup * 2 u . Fb [pop] [Fw] while popopd\n",
" u dup * 2 u . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
" u dup * 2 u [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" u dup * 2 . [sqr] dip 2 // u [pop] [Fw] while popopd\n",
" u dup * 2 [sqr] . dip 2 // u [pop] [Fw] while popopd\n",
" u dup * . sqr 2 2 // u [pop] [Fw] while popopd\n",
" u dup * . dup mul 2 2 // u [pop] [Fw] while popopd\n",
" u dup * dup * . 2 2 // u [pop] [Fw] while popopd\n",
" ^^^^^^^^^^^^^\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"w/ `K == u dup * dup *`\n",
"\n",
" K 1 u [pop] [Fw] . while popopd\n",
" K 1 u . Fw [pop] [Fw] while popopd\n",
" K 1 u . [pop odd] [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" K 1 u [pop odd] . [Ft] [] ifte Fb [pop] [Fw] while popopd\n",
" K 1 u [pop odd] [Ft] . [] ifte Fb [pop] [Fw] while popopd\n",
" K 1 u [pop odd] [Ft] [] . ifte Fb [pop] [Fw] while popopd\n",
" K 1 u . Ft Fb [pop] [Fw] while popopd\n",
" K 1 u . [over] dip * Fb [pop] [Fw] while popopd\n",
" K 1 u [over] . dip * Fb [pop] [Fw] while popopd\n",
" K 1 . over u * Fb [pop] [Fw] while popopd\n",
" K 1 K . u * Fb [pop] [Fw] while popopd\n",
" K 1 K u . * Fb [pop] [Fw] while popopd\n",
" K 1 K u * . Fb [pop] [Fw] while popopd\n",
" ^^^^^"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"w/ `L == K u *`\n",
"\n",
" K 1 L . Fb [pop] [Fw] while popopd\n",
" K 1 L . [[sqr] dip 2 //] dip [pop] [Fw] while popopd\n",
" K 1 L [[sqr] dip 2 //] . dip [pop] [Fw] while popopd\n",
" K 1 . [sqr] dip 2 // L [pop] [Fw] while popopd\n",
" K 1 [sqr] . dip 2 // L [pop] [Fw] while popopd\n",
" K . sqr 1 2 // L [pop] [Fw] while popopd\n",
" K . dup mul 1 2 // L [pop] [Fw] while popopd\n",
" K K . mul 1 2 // L [pop] [Fw] while popopd\n",
" K K * . 1 2 // L [pop] [Fw] while popopd\n",
" ^^^^^\n",
" K K * . 1 2 // L [pop] [Fw] while popopd\n",
" K K * 1 . 2 // L [pop] [Fw] while popopd\n",
" K K * 1 2 . // L [pop] [Fw] while popopd\n",
" K K * 0 . L [pop] [Fw] while popopd\n",
" K K * 0 L . [pop] [Fw] while popopd\n",
" K K * 0 L [pop] . [Fw] while popopd\n",
" K K * 0 L [pop] [Fw] . while popopd\n",
" ^^^^^\n",
" K K * 0 L . popopd\n",
" L . "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So:\n",
"\n",
" K == u dup * dup *\n",
" L == K u *\n",
"\n",
"Our result \"thunk\" would be:\n",
" \n",
" u dup * dup * u *\n",
"\n",
"Mechanically, you could do:\n",
"\n",
" u dup * dup * u *\n",
" u u [dup * dup *] dip *\n",
" u dup [dup * dup *] dip *\n",
"\n",
"\n",
" F5 == dup [dup * dup *] dip *\n",
"\n",
"But we can swap the two arguments to the final `*` to get all mentions of `u` to the left:\n",
"\n",
"\n",
" u u dup * dup * *\n",
"\n",
"\n",
"Then de-duplicate \"u\":\n",
"\n",
"\n",
" u dup dup * dup * *\n",
"\n",
"\n",
"To arrive at a startlingly elegant form for F5:\n",
"\n",
"\n",
" F5 == dup dup * dup * *"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" u . dup dup * dup * *\n",
" u u . dup * dup * *\n",
" u u u . * dup * *\n",
" u u**2 . dup * *\n",
"u u**2 u**2 . * *\n",
" u u**4 . *\n",
" u**5 . \n"
]
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAABgAAAAWCAYAAADafVyIAAAABHNCSVQICAgIfAhkiAAAAUpJREFUSInt1DtLXUEUBeBPESLXFGITsDEqEdHKaLBMQBvFRsh/SG9nKouAjY0/IsQm2lgoNrENeaEgaKGVjyBaBLQQNRYzSYbjOVduzoWkcMGwmb1n1pr9YPjPMYOfmXWUHmiqg8g2XiT7q3oLXMq8OkVjHQS6sI89vMPjNNhQknwMFezgEabRh36cluTORQu+Y+qXI1ui18IkTOZc7oixxSoCZ9jCkyKBp9F+zrk8FO3XKgLN6MVh0YE9HBfEZoUMJhLfHJ6jE8NYxg8h21toiwQrBQJrMd6e+BZwgAthkt4LTc7FaCR4UxA/ERpYE9IeDEabV/8uIcMvZQQGos0jGY+2WoPvxDehllk8wKZQvpdlBD5Gkp7E14K3/vyU3bWSpp/dKp5hHUt4iBFsCHNdwe5fPPw3mjEvjN05PuEVWnGND2XI7/HvcAOaJEK/e6V+UwAAAABJRU5ErkJggg==\n",
"text/latex": [
"$$u^{5}$$"
],
"text/plain": [
" 5\n",
"u "
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"stack = list_to_stack([sympy.symbols('u')])\n",
"viewer = TracePrinter()\n",
"try:\n",
" (result, _) = run('dup dup * dup * *', stack, D, viewer.viewer)[0]\n",
"except Exception, e:\n",
" print e\n",
"viewer.print_()\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I'm not sure how to implement these kinds of thunks. I think you have to have support in the interpreter, or you have to modify all of the functions like `dup` to check for thunks in their inputs."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Working on the compiler, from this:\n",
"\n",
" dup dup * dup * *\n",
"\n",
"We can already generate:\n",
"\n",
" ---------------------------------\n",
" (a0, stack) = stack\n",
" a1 = mul(a0, a0)\n",
" a2 = mul(a1, a1)\n",
" a3 = mul(a2, a0)\n",
" stack = (a3, stack)\n",
" ---------------------------------\n",
"\n",
"This is pretty old stuff... (E.g. from 1999, M. Anton Ertl [Compilation of Stack-Based Languages](http://www.complang.tuwien.ac.at/projects/rafts.html) he goes a lot further for Forth.)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## \"A Transformation Based Approach to Semantics-Directed Code Generation\"\n",
"\n",
"by Arthur Nunes-Harwitt\n",
"\n",
"https://dl.acm.org/citation.cfm?doid=2635648.2635652\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6\n"
]
}
],
"source": [
"def m(x, y): return x * y\n",
"\n",
"print m(2, 3)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"6\n"
]
}
],
"source": [
"def m(x): return lambda y: x * y\n",
"\n",
"print m(2)(3)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lambda y: 2 * y\n",
"6\n"
]
}
],
"source": [
"def m(x): return \"lambda y: %(x)s * y\" % locals()\n",
"\n",
"print m(2)\n",
"print eval(m(2))(3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In Joy:\n",
"\n",
" m == [*] cons\n",
"\n",
" 3 2 m i\n",
" 3 2 [*] cons i\n",
" 3 [2 *] i\n",
" 3 2 *\n",
" 6\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lambda b: 1 if 3 == 0 else b * p(3 - 1, b)\n"
]
}
],
"source": [
"def p(n, b): # original\n",
" return 1 if n == 0 else b * p(n - 1, b)\n",
"\n",
"\n",
"def p(n): # curried\n",
" return lambda b: 1 if n == 0 else b * p(n - 1, b)\n",
"\n",
"\n",
"def p(n): # quoted\n",
" return \"lambda b: 1 if %(n)s == 0 else b * p(%(n)s - 1, b)\" % locals()\n",
"\n",
"\n",
"print p(3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Original\n",
"\n",
" p == [0 =] [popop 1] [-- over] [dip *] genrec\n",
"\n",
" b n p\n",
" b n [0 =] [popop 1] [-- over [p] dip *]\n",
"\n",
" b n -- over [p] dip *\n",
" b n-1 over [p] dip *\n",
" b n-1 b [p] dip *\n",
" b n-1 p b *\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"curried, quoted\n",
"\n",
" n p\n",
" ---------------------------------------------\n",
" [[n 0 =] [pop 1] [dup n --] [*] genrec]"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lambda b: b * p(3 - 1, b)\n"
]
}
],
"source": [
"def p(n): # lambda lowered\n",
" return (\n",
" lambda b: 1\n",
" if n == 0 else\n",
" lambda b: b * p(n - 1, b)\n",
" )\n",
"\n",
"\n",
"def p(n): # lambda lowered quoted\n",
" return (\n",
" \"lambda b: 1\"\n",
" if n == 0 else\n",
" \"lambda b: b * p(%(n)s - 1, b)\" % locals()\n",
" )\n",
"\n",
"print p(3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
" p == [0 =] [[pop 1]] [ [-- [dup] dip p *] cons ]ifte\n",
"\n",
"\n",
" 3 p\n",
" 3 [-- [dup] dip p *] cons\n",
" [3 -- [dup] dip p *]\n"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"8\n"
]
}
],
"source": [
"def p(n): # expression lifted\n",
" if n == 0:\n",
" return lambda b: 1\n",
" f = p(n - 1)\n",
" return lambda b: b * f(b)\n",
"\n",
"\n",
"print p(3)(2)"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"lambda b: b * (lambda b: b * (lambda b: b * (lambda b: 1)(b))(b))(b)\n",
"8\n"
]
}
],
"source": [
"def p(n): # quoted\n",
" if n == 0:\n",
" return \"lambda b: 1\"\n",
" f = p(n - 1)\n",
" return \"lambda b: b * (%(f)s)(b)\" % locals()\n",
"\n",
"print p(3)\n",
"print eval(p(3))(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" p == [0 =] [pop [pop 1]] [-- p [dupdip *] cons] ifte\n",
"\n",
"\n",
" 3 p\n",
" 3 -- p [dupdip *] cons\n",
" 2 p [dupdip *] cons\n",
" 2 -- p [dupdip *] cons [dupdip *] cons\n",
" 1 p [dupdip *] cons [dupdip *] cons\n",
" 1 -- p [dupdip *] cons [dupdip *] cons [dupdip *] cons\n",
" 0 p [dupdip *] cons [dupdip *] cons [dupdip *] cons\n",
" 0 pop [pop 1] [dupdip *] cons [dupdip *] cons [dupdip *] cons\n",
" [pop 1] [dupdip *] cons [dupdip *] cons [dupdip *] cons\n",
" ...\n",
" [[[[pop 1] dupdip *] dupdip *] dupdip *]\n",
"\n",
"\n",
" 2 [[[[pop 1] dupdip *] dupdip *] dupdip *] i\n",
" 2 [[[pop 1] dupdip *] dupdip *] dupdip *\n",
" 2 [[pop 1] dupdip *] dupdip * 2 *\n",
" 2 [pop 1] dupdip * 2 * 2 *\n",
" 2 pop 1 2 * 2 * 2 *\n",
" 1 2 * 2 * 2 *\n",
"\n",
"\n",
"\n",
" p == [0 =] [pop [pop 1]] [-- p [dupdip *] cons] ifte\n",
" p == [0 =] [pop [pop 1]] [-- [p] i [dupdip *] cons] ifte\n",
" p == [0 =] [pop [pop 1]] [--] [i [dupdip *] cons] genrec"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"define('p == [0 =] [pop [pop 1]] [--] [i [dupdip *] cons] genrec')"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[[[[pop 1] dupdip *] dupdip *] dupdip *]\n"
]
}
],
"source": [
"J('3 p')"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" . 2 [[[[pop 1] dupdip *] dupdip *] dupdip *] i\n",
" 2 . [[[[pop 1] dupdip *] dupdip *] dupdip *] i\n",
"2 [[[[pop 1] dupdip *] dupdip *] dupdip *] . i\n",
" 2 . [[[pop 1] dupdip *] dupdip *] dupdip *\n",
" 2 [[[pop 1] dupdip *] dupdip *] . dupdip *\n",
" 2 . [[pop 1] dupdip *] dupdip * 2 *\n",
" 2 [[pop 1] dupdip *] . dupdip * 2 *\n",
" 2 . [pop 1] dupdip * 2 * 2 *\n",
" 2 [pop 1] . dupdip * 2 * 2 *\n",
" 2 . pop 1 2 * 2 * 2 *\n",
" . 1 2 * 2 * 2 *\n",
" 1 . 2 * 2 * 2 *\n",
" 1 2 . * 2 * 2 *\n",
" 2 . 2 * 2 *\n",
" 2 2 . * 2 *\n",
" 4 . 2 *\n",
" 4 2 . *\n",
" 8 . \n"
]
}
],
"source": [
"V('2 [[[[pop 1] dupdip *] dupdip *] dupdip *] i')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"stack = list_to_stack([sympy.symbols('u')])\n",
"(result, s) = run('p i', stack, D)[0]\n",
"result"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"From this:\n",
"\n",
" p == [0 =] [pop pop 1] [-- over] [dip *] genrec\n",
"\n",
"To this:\n",
"\n",
" p == [0 =] [pop [pop 1]] [--] [i [dupdip *] cons] genrec\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Try it with `F()`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def odd(n): return n % 2\n",
"\n",
"\n",
"def F(u, k):\n",
" z = 1\n",
" while k != 0:\n",
" if odd(k):\n",
" z = z * u\n",
" k = k / 2\n",
" u = u * u\n",
" return z\n",
"\n",
"F(2, 5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" def _F(u, k=k):\n",
" z = 1\n",
" while k != 0:\n",
" if odd(k):\n",
" z = z * u\n",
" k = k / 2\n",
" u = u * u\n",
" return z\n",
" return _F\n",
" \n",
"F(5)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" def _F(u, k=k):\n",
" if k == 0:\n",
" z = 1\n",
" else:\n",
" z = F(k / 2)(u)\n",
" z *= z\n",
" if odd(k):\n",
" z = z * u\n",
" return z\n",
" return _F\n",
" \n",
"F(5)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = lambda u: 1\n",
" else:\n",
" f = F(k / 2)\n",
" def z(u):\n",
" uu = f(u)\n",
" uu *= uu\n",
" return uu * u if odd(k) else uu\n",
" return z\n",
" \n",
"F(5)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = lambda u: 1\n",
" else:\n",
" f = F(k / 2)\n",
" if odd(k):\n",
" z = lambda u: (lambda fu, u: fu * fu * u)(f(u), u)\n",
" else:\n",
" z = lambda u: (lambda fu, u: fu * fu)(f(u), u)\n",
" return z\n",
" \n",
"F(5)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = \"lambda u: 1\"\n",
" else:\n",
" f = F(k / 2)\n",
" if odd(k):\n",
" z = \"lambda u: (lambda fu, u: fu * fu * u)((%(f)s)(u), u)\" % locals()\n",
" else:\n",
" z = \"lambda u: (lambda fu, u: fu * fu)((%(f)s)(u), u)\" % locals()\n",
" return z\n",
" \n",
"source = F(5)\n",
"print source\n",
"eval(source)(2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hmm..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for n in range(4):\n",
" print F(n)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = \"lambda u: 1\"\n",
" elif k == 1:\n",
" z = \"lambda u: u\"\n",
" else:\n",
" f = F(k / 2)\n",
" if odd(k):\n",
" z = \"lambda u: (lambda fu, u: fu * fu * u)((%(f)s)(u), u)\" % locals()\n",
" else:\n",
" z = \"lambda u: (lambda fu, u: fu * fu)((%(f)s)(u), u)\" % locals()\n",
" return z\n",
" \n",
"source = F(5)\n",
"print source\n",
"eval(source)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for n in range(4):\n",
" print F(n)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = \"lambda u: 1\"\n",
" elif k == 1:\n",
" z = \"lambda u: u\"\n",
" else:\n",
" m = k / 2\n",
" if odd(k):\n",
" if m == 0:\n",
" z = \"lambda u: 1\"\n",
" elif m == 1:\n",
" z = \"lambda u: u * u * u\"\n",
" else:\n",
" z = \"lambda u: (lambda fu, u: fu * fu * u)((%s)(u), u)\" % F(m)\n",
" else:\n",
" if m == 0:\n",
" z = \"lambda u: 1\"\n",
" elif m == 1:\n",
" z = \"lambda u: u * u\"\n",
" else:\n",
" z = \"lambda u: (lambda u: u * u)((%s)(u))\" % F(m)\n",
" return z\n",
" \n",
"source = F(5)\n",
"print source\n",
"eval(source)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(k):\n",
" if k == 0:\n",
" z = \"lambda u: 1\"\n",
" elif k == 1:\n",
" z = \"lambda u: u\"\n",
" else:\n",
" m = k / 2\n",
" if m == 0:\n",
" z = \"lambda u: 1\"\n",
" \n",
" elif odd(k):\n",
" if m == 1:\n",
" z = \"lambda u: u * u * u\"\n",
" else:\n",
" z = \"lambda u: (lambda fu, u: fu * fu * u)((%s)(u), u)\" % F(m)\n",
" else:\n",
" if m == 1:\n",
" z = \"lambda u: u * u\"\n",
" else:\n",
" z = \"lambda u: (lambda u: u * u)((%s)(u))\" % F(m)\n",
" return z\n",
" \n",
"source = F(5)\n",
"print source\n",
"eval(source)(2)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"for n in range(7):\n",
" source = F(n)\n",
" print n, '%2i' % eval(source)(2), source"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"So that gets pretty good, eh?\n",
"\n",
"\n",
"But looking back at the definition in Joy, it doesn't seem easy to directly apply this technique to Joy code:\n",
"\n",
" Ft == [over] dip *\n",
" Fb == [[sqr] dip 2 //] dip\n",
" Fw == [pop odd] [Ft] [] ifte Fb\n",
" F == 1 [pop] [Fw] while popopd\n",
"\n",
"\n",
"But a direct translation of the Python code..?\n",
"\n",
"\n",
" F == [\n",
" [[0 =] [pop 1]]\n",
" [[1 =] []]\n",
" [_F.0]\n",
" ] cond\n",
"\n",
" _F.0 == dup 2 // [\n",
" [[0 =] [pop 1]]\n",
" [[pop odd] _F.1]\n",
" [_F.2]\n",
" ] cond\n",
"\n",
" _F.1 == [1 =] [pop [dup dup * *]] [popd F [dupdip over * *] cons] ifte\n",
" _F.2 == [1 =] [pop [dup *]] [popd F [i dup *] cons] ifte\n",
"\n",
"\n",
"Try it:\n",
"\n",
" 5 F\n",
" 5 [ [[0 =] [pop 1]] [[1 =] []] [_F.0] ] cond\n",
" 5 _F.0\n",
" 5 dup 2 // [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
" 5 5 2 // [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
"\n",
" 5 2 [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
" 5 2 _F.1\n",
" 5 2 [1 =] [popop [dup dup * *]] [popd F [dupdip over * *] cons] ifte\n",
" 5 2 popd F [dupdip over * *] cons\n",
" 2 F [dupdip over * *] cons\n",
"\n",
" 2 F [dupdip over * *] cons\n",
"\n",
" 2 F\n",
" 2 [ [[0 =] [pop 1]] [[1 =] []] [_F.0] ] cond\n",
" 2 _F.0\n",
" 2 dup 2 // [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
" 2 2 2 // [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
" 2 1 [ [[0 =] [pop 1]] [[pop odd] _F.1] [_F.2] ] cond\n",
" 2 1 _F.2\n",
" 2 1 [1 =] [popop [dup *]] [popd F [i dup *] cons] ifte\n",
" 2 1 popop [dup *]\n",
" [dup *]\n",
"\n",
"\n",
" 2 F [dupdip over * *] cons\n",
" [dup *] [dupdip over * *] cons\n",
" [[dup *] dupdip over * *]\n",
"\n",
"And here it is in action:\n",
"\n",
" 2 [[dup *] dupdip over * *] i\n",
" 2 [dup *] dupdip over * *\n",
" 2 dup * 2 over * *\n",
" 2 2 * 2 over * *\n",
" 4 2 over * *\n",
" 4 2 4 * *\n",
" 4 8 *\n",
" 32\n",
"\n",
"\n",
"\n",
"So, it works, but in this case the results of the partial evaluation are more elegant.\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Try it with `hylomorphism()`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c, F, P, G):\n",
" '''Return a hylomorphism function H.'''\n",
"\n",
" def H(a):\n",
" if P(a):\n",
" result = c\n",
" else:\n",
" b, aa = G(a)\n",
" result = F(b, H(aa))\n",
" return result\n",
"\n",
" return H"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### First, curry\n",
"\n",
"With abuse of syntax:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" return lambda F: lambda P: lambda G: lambda a: (\n",
" if P(a):\n",
" result = c\n",
" else:\n",
" b, aa = G(a)\n",
" result = F(b)(H(aa))\n",
" return result\n",
" )\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### lambda lowering\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" def r(a):\n",
" def rr(P):\n",
" if P(a):\n",
" return lambda F: lambda G: c\n",
" return lambda F: lambda G: (\n",
" b, aa = G(a)\n",
" return F(b)(H(aa))\n",
" )\n",
" return rr\n",
" return r\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### expression lifting\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" def r(a):\n",
" def rr(P):\n",
" def rrr(G):\n",
" if P(a):\n",
" return lambda F: c\n",
" b, aa = G(a)\n",
" H = hylomorphism(c)(aa)(P)(G)\n",
" return lambda F: F(b)(H(F))\n",
" return rrr\n",
" return rr\n",
" return r\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### quoted\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" def r(a):\n",
" def rr(P):\n",
" def rrr(G):\n",
" if P(a):\n",
" return \"lambda F: %s\" % (c,)\n",
" b, aa = G(a)\n",
" H = hylomorphism(c)(aa)(P)(G)\n",
" return \"lambda F: F(%(b)s)((%(H)s)(F))\" % locals()\n",
" return rrr\n",
" return rr\n",
" return r\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hylomorphism(0)(3)(lambda n: n == 0)(lambda n: (n-1, n-1))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def F(a):\n",
" def _F(b):\n",
" print a, b\n",
" return a + b\n",
" return _F\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"F(2)(3)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eval(hylomorphism(0)(5)(lambda n: n == 0)(lambda n: (n-1, n-1)))(F)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eval(hylomorphism([])(5)(lambda n: n == 0)(lambda n: (n-1, n-1)))(lambda a: lambda b: [a] + b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hylomorphism(0)([1, 2, 3])(lambda n: not n)(lambda n: (n[0], n[1:]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"hylomorphism([])([1, 2, 3])(lambda n: not n)(lambda n: (n[1:], n[1:]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"eval(hylomorphism([])([1, 2, 3])(lambda n: not n)(lambda n: (n[1:], n[1:])))(lambda a: lambda b: [a] + b)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" return lambda a: lambda P: (\n",
" if P(a):\n",
" result = lambda F: lambda G: c\n",
" else:\n",
" result = lambda F: lambda G: (\n",
" b, aa = G(a)\n",
" return F(b)(H(aa))\n",
" )\n",
" return result\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" return lambda a: (\n",
" lambda F: lambda P: lambda G: c\n",
" if P(a) else\n",
" lambda F: lambda P: lambda G: (\n",
" b, aa = G(a)\n",
" return F(b)(H(aa))\n",
" )\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def hylomorphism(c):\n",
" return lambda a: lambda G: (\n",
" lambda F: lambda P: c\n",
" if P(a) else\n",
" b, aa = G(a)\n",
" lambda F: lambda P: F(b)(H(aa))\n",
" )\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.15"
}
},
"nbformat": 4,
"nbformat_minor": 2
}