Skip to content

Instantly share code, notes, and snippets.

@shashi
Last active April 1, 2023 12:37
Show Gist options
  • Save shashi/9ad9de91d1aa12f006c4 to your computer and use it in GitHub Desktop.
Save shashi/9ad9de91d1aa12f006c4 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"using APL"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Basic expressions"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5x5 Array{Int64,2}:\n",
" 1 2 3 4 5\n",
" 2 4 6 8 10\n",
" 3 6 9 12 15\n",
" 4 8 12 16 20\n",
" 5 10 15 20 25"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"(ι5) ×∘ ι5\""
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{((ι ω) (×∘) (ι ω))}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f = apl\"{(ιω) ×∘ ιω}\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Make in APL, use in Julia"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5x5 Array{Int64,2}:\n",
" 1 2 3 4 5\n",
" 2 4 6 8 10\n",
" 3 6 9 12 15\n",
" 4 8 12 16 20\n",
" 5 10 15 20 25"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f(5)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1-element Array{Int64,1}:\n",
" 55"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"+/\"(1:10)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Below is a reproductoin of [Alan's APL notebook](https://github.com/alanedelman/ExploringIntroCS/blob/master/apl.ipynb)**"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{(((ι (ρ ω)) = (ω ι ω)) ] ω)}"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"uniq = apl\"{((ιρω) = (ω ι ω))]ω}\" # ] is the getindex operator"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5-element Array{Int64,1}:\n",
" 3\n",
" 2\n",
" 1\n",
" 4\n",
" 7"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v = [3, 2, 1, 3, 4, 2, 1, 7, 4, 2, 2, 3]\n",
"x = uniq(v)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5x2 Array{Int64,2}:\n",
" 3 3\n",
" 2 4\n",
" 1 2\n",
" 4 2\n",
" 7 1"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Frequency distribution\n",
"[x apl\"{+/(α=∘ω)}\"(x,v)]"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3x3 Array{Int64,2}:\n",
" 3 0 0\n",
" 6 7 2\n",
" 13 11 11"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"16 16 16 ⊤ 877 123 43\""
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 2\n",
" 1\n",
" 11"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"⊤\"([1760,3,12],95) # 95 inches = 2 yards, 1 foot, 11 inches"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3-element Array{Int64,1}:\n",
" 2\n",
" 1\n",
" 2"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"P=[2, 3, 7] # List of primes\n",
"E=[2, 1, 2] # List of exponents"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"1x18 Array{Int64,2}:\n",
" 1 7 49 3 21 147 2 14 98 6 42 294 4 28 196 12 84 588"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#prod(P.^⊤(E+1 ,R ),1)\n",
"\n",
"apl\"{×⌿α*(ω+1)⊤(⁻1+ι×/ω+1)}\"(P, E)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6x5 Array{Int64,2}:\n",
" 1 3 6 10 15\n",
" 2 5 9 14 20\n",
" 4 8 13 19 24\n",
" 7 12 18 23 27\n",
" 11 17 22 26 29\n",
" 16 21 25 28 30"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"6 5 ρ ⍋⍋,(ι6)+∘ι5\""
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6x4 Array{Int64,2}:\n",
" 3 16 10 11\n",
" 5 1 14 14\n",
" 19 8 6 17\n",
" 1 2 11 14\n",
" 1 8 2 9\n",
" 14 12 19 17"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Dijkstra's Question \n",
"M=[3 16 10 11;5 1 14 14;19 8 6 17;1 2 11 14; 1 8 2 9; 14 12 19 17]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2-element Array{UnitRange{Int64},1}:\n",
" 1:6\n",
" 1:4"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x =apl\"{ι¨ρω]ω}\"(M)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2-element Array{Int64,1}:\n",
" 6\n",
" 9"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"{ (ω=(1]α) +∘ (2]α)) ] ω}\"(x,M)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(\n",
"6x4 Array{Int64,2}:\n",
" 3 16 10 11\n",
" 5 1 14 14\n",
" 19 8 6 17\n",
" 1 2 11 14\n",
" 1 8 2 9\n",
" 14 12 19 17,\n",
"\n",
"4x6 Array{Int64,2}:\n",
" 3 5 19 1 1 14\n",
" 16 1 8 2 8 12\n",
" 10 14 6 11 2 19\n",
" 11 14 17 14 9 17)"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"{ω⍉1 2}\"(M),apl\"{ω⍉2 1}\"(M)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### This is why I love Julia..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here's the implementation explained in brief\n",
"\n",
"The `apl\"\"` string macro parses and evals an APL expression. The parser works on the reverse of the string, and consists of a bunch of [concatenation rules](https://github.com/shashi/APL.jl/blob/06570f535862f934e3da12d238501f67b210aec6/src/parser.jl#L4-L41) defined as a generic `cons` function.\n",
"\n",
"APL strings are parsed and executed to produce either a result or an object representing the APL expression. Primitve functions are of the type `PrimFn{c}` where `c` is the character, similarly operators are of type `Op1{c, F}` and `Op2{c, F1, F2}` where `F`, `F1` and `F2` are types of the operand functions - these type parameters let you specialize how these objects are handled all over the place. an optimization is simply a method defined on an expression of a specific type\n",
"\n",
"The `call` generic function can be used to make these objects callable! The [eval-apply is really simple](https://github.com/shashi/APL.jl/blob/master/src/eval.jl) and quite elegant.\n",
"\n",
"Here's a look at what the JIT produces:"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define i64 @julia_call_22549(i64, i64) {\n",
"top:\n",
" %2 = sub i64 %0, %1\n",
" ret i64 %2\n",
"}\n"
]
}
],
"source": [
"@code_llvm apl\"-\"(1, 2)"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define double @julia_call_22573(i64, double) {\n",
"top:\n",
" %2 = sitofp i64 %0 to double\n",
" %3 = fsub double %2, %1\n",
" ret double %3\n",
"}\n"
]
}
],
"source": [
"@code_llvm apl\"-\"(1, 2.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Which is the exact same as"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define i64 @julia_-_22576(i64, i64) {\n",
"top:\n",
" %2 = sub i64 %0, %1\n",
" ret i64 %2\n",
"}\n"
]
}
],
"source": [
"@code_llvm 1-2"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define double @julia_-_22577(i64, double) {\n",
"top:\n",
" %2 = sitofp i64 %0 to double\n",
" %3 = fsub double %2, %1\n",
" ret double %3\n",
"}\n"
]
}
],
"source": [
"@code_llvm 1-2.0"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define i64 @julia_call_22583(i64, i64) {\n",
"top:\n",
" %2 = sub i64 %1, %0\n",
" ret i64 %2\n",
"}\n"
]
}
],
"source": [
"@code_llvm apl\"-⍨\"(1,2)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define i64 @julia_call_22596(i64, i64) {\n",
"top:\n",
" %2 = sub i64 %0, %1\n",
" ret i64 %2\n",
"}\n"
]
}
],
"source": [
"@code_llvm apl\"-⍨⍨⍨⍨⍨⍨\"(1,2) # Up to 6 flips get inlined!"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"define %jl_value_t* @julia_call_22607(%jl_value_t*) {\n",
"top:\n",
" %1 = call %jl_value_t* @julia_map_22608(%jl_value_t* %0)\n",
" ret %jl_value_t* %1\n",
"}\n"
]
}
],
"source": [
"@code_llvm apl\"-¨\"([1,2,3]) # some things won't be inlined..."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Identity elements for dyadic functions and element type combinations are defined [here](https://github.com/shashi/APL.jl/blob/06570f535862f934e3da12d238501f67b210aec6/src/defns.jl#L120-L133)\n",
"\n",
"They continue to work when an operator modifes the function"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"([0.0],[1.0],[1.0],[-Inf],[Inf],[Any[]],[-Inf],[1.0],[0.0],[0])"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"+/⍬\",apl\"×/⍬\", apl\"×/⍬\", apl\"⌈/⍬\", apl\"⌊/⍬\", apl\",/⍬\", apl\"⌈/⍬\", apl\"∧/⍬\", apl\"∨/⍬\", apl\"+/\"(Bool[])"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"([0.0],[1.0],[1.0],[-Inf],[Inf],[Any[]],[-Inf],[1.0],[0.0],[0])"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"apl\"+⍨/⍬\",apl\"×⍨/⍬\", apl\"×⍨/⍬\", apl\"⌈⍨/⍬\", apl\"⌊⍨/⍬\", apl\",⍨/⍬\", apl\"⌈⍨/⍬\", apl\"∧⍨/⍬\", apl\"∨⍨/⍬\", apl\"+⍨/\"(Bool[])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.4.0-rc1",
"language": "julia",
"name": "julia-0.4"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.4.0"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
@vendethiel
Copy link

A few of these aren't correct.

apl"(ι5) ×∘ ι5"

First, the symbol in APL is , not ι.
Second, this would be an atop (×∘), which is not what you want: what you want is outer product.

In APL (at least Dyalog APL), that's ∘.×.

    (⍳5)∘.×⍳5
1  2  3  4  5
2  4  6  8 10
3  6  9 12 15
4  8 12 16 20
5 10 15 20 25

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment