{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Replacing Functions in the Dictionary\n",
    "For now, there is no way to define new functions from within the Joy language.  All functions (and the interpreter) all accept and return a dictionary parameter (in addition to the stack and expression) so that we can implement e.g. a function that adds new functions to the dictionary.  However, there's no function that does that.  Adding a new function to the dictionary is a meta-interpreter action, you have to do it in Python, not Joy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from notebook_preamble import D, J, V"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A long trace"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                  . [23 18] average\n",
      "                          [23 18] . average\n",
      "                          [23 18] . [sum 1.0 *] [size] cleave /\n",
      "              [23 18] [sum 1.0 *] . [size] cleave /\n",
      "       [23 18] [sum 1.0 *] [size] . cleave /\n",
      "       [23 18] [sum 1.0 *] [size] . [i] app2 [popd] dip /\n",
      "   [23 18] [sum 1.0 *] [size] [i] . app2 [popd] dip /\n",
      "[23 18] [[sum 1.0 *] [23 18]] [i] . infra first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "              [23 18] [sum 1.0 *] . i [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                          [23 18] . sum 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                               41 . 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                           41 1.0 . * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                             41.0 . [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                   41.0 [[23 18]] . swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                   [23 18] [41.0] . first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                     [23 18] 41.0 . [[size] [23 18]] [i] infra first [popd] dip /\n",
      "    [23 18] 41.0 [[size] [23 18]] . [i] infra first [popd] dip /\n",
      "[23 18] 41.0 [[size] [23 18]] [i] . infra first [popd] dip /\n",
      "                   [23 18] [size] . i [41.0 [23 18]] swaack first [popd] dip /\n",
      "                          [23 18] . size [41.0 [23 18]] swaack first [popd] dip /\n",
      "                          [23 18] . 0 swap [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                        [23 18] 0 . swap [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                        0 [23 18] . [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "               0 [23 18] [pop ++] . step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                    0 23 [pop ++] . i [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                             0 23 . pop ++ [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                                0 . ++ [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                                1 . [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                           1 [18] . [pop ++] step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                  1 [18] [pop ++] . step [41.0 [23 18]] swaack first [popd] dip /\n",
      "                    1 18 [pop ++] . i [41.0 [23 18]] swaack first [popd] dip /\n",
      "                             1 18 . pop ++ [41.0 [23 18]] swaack first [popd] dip /\n",
      "                                1 . ++ [41.0 [23 18]] swaack first [popd] dip /\n",
      "                                2 . [41.0 [23 18]] swaack first [popd] dip /\n",
      "                 2 [41.0 [23 18]] . swaack first [popd] dip /\n",
      "                 [23 18] 41.0 [2] . first [popd] dip /\n",
      "                   [23 18] 41.0 2 . [popd] dip /\n",
      "            [23 18] 41.0 2 [popd] . dip /\n",
      "                     [23 18] 41.0 . popd 2 /\n",
      "                             41.0 . 2 /\n",
      "                           41.0 2 . /\n",
      "                             20.5 . \n"
     ]
    }
   ],
   "source": [
    "V('[23 18] average')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Replacing `size` with a Python version\n",
    "\n",
    "Both `sum` and `size` each convert a sequence to a single value."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "     sum == 0 swap [+] step\n",
    "    size == 0 swap [pop ++] step"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "An efficient `sum` function is already in the library. But for `size` we can use a “compiled” version hand-written in Python to speed up evaluation and make the trace more readable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from joy.library import SimpleFunctionWrapper\n",
    "from joy.utils.stack import iter_stack\n",
    "\n",
    "\n",
    "@SimpleFunctionWrapper\n",
    "def size(stack):\n",
    "    '''Return the size of the sequence on the stack.'''\n",
    "    sequence, stack = stack\n",
    "    n = 0\n",
    "    for _ in iter_stack(sequence):\n",
    "        n += 1\n",
    "    return n, stack"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we replace the old version in the dictionary with the new version, and re-evaluate the expression."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "D['size'] = size"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## A shorter trace\n",
    "You can see that `size` now executes in a single step."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                  . [23 18] average\n",
      "                          [23 18] . average\n",
      "                          [23 18] . [sum 1.0 *] [size] cleave /\n",
      "              [23 18] [sum 1.0 *] . [size] cleave /\n",
      "       [23 18] [sum 1.0 *] [size] . cleave /\n",
      "       [23 18] [sum 1.0 *] [size] . [i] app2 [popd] dip /\n",
      "   [23 18] [sum 1.0 *] [size] [i] . app2 [popd] dip /\n",
      "[23 18] [[sum 1.0 *] [23 18]] [i] . infra first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "              [23 18] [sum 1.0 *] . i [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                          [23 18] . sum 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                               41 . 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                           41 1.0 . * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                             41.0 . [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                   41.0 [[23 18]] . swaack first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                   [23 18] [41.0] . first [[size] [23 18]] [i] infra first [popd] dip /\n",
      "                     [23 18] 41.0 . [[size] [23 18]] [i] infra first [popd] dip /\n",
      "    [23 18] 41.0 [[size] [23 18]] . [i] infra first [popd] dip /\n",
      "[23 18] 41.0 [[size] [23 18]] [i] . infra first [popd] dip /\n",
      "                   [23 18] [size] . i [41.0 [23 18]] swaack first [popd] dip /\n",
      "                          [23 18] . size [41.0 [23 18]] swaack first [popd] dip /\n",
      "                                2 . [41.0 [23 18]] swaack first [popd] dip /\n",
      "                 2 [41.0 [23 18]] . swaack first [popd] dip /\n",
      "                 [23 18] 41.0 [2] . first [popd] dip /\n",
      "                   [23 18] 41.0 2 . [popd] dip /\n",
      "            [23 18] 41.0 2 [popd] . dip /\n",
      "                     [23 18] 41.0 . popd 2 /\n",
      "                             41.0 . 2 /\n",
      "                           41.0 2 . /\n",
      "                             20.5 . \n"
     ]
    }
   ],
   "source": [
    "V('[23 18] average')"
   ]
  }
 ],
 "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.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
