NYCJUG/2013-12-10/UsingAPLtoWriteBrowserCode
< NYCJUG | 2013-12-10
Jump to navigation
Jump to search
Using APL to Write Browser Code
Here’s an example of a simple browser page (at http://home.comcast.net/~paul.l.jackson/APL.js/Hosting.html) written in APL:
The source for this consists of the following files:
File Size Description Hosting.html 3,216 Top-level HTML that implements page. APL\NameSpaces.js 16,441 APL functions Hosting\apl.js 155,324 Javascript implementation of APL interpreter Hosting\aplHosting.js 491 Sets up APL workspace upon loading of page
The HTML below pulls in the definitions of the APL functions with these lines:
thisAPL = apl.ws() thisAPL(_LIB_["Dates"] + _LIB_["Numbers"])
The Roman number handling is done by this JavaScript code that simply calls the APL to do the more complex work:
if (isRoman) { if (aRoman.value.trim().length == 0) {return false} // NB. fromRoman needs its argument in quotes aNumber.value = callAPL("fromRoman " + quote(aRoman.value)) } else { if (aNumber.value.trim().length == 0) {return false} aRoman.value = callAPL("toRoman " + aNumber.value) }
Here’s the complete source code for the top-level HTML that implements the site; an example of the APL definitions is given after this.
<!DOCTYPE html> <html><head> <meta charset="UTF-8"> <title>APL.js Hosting Compiled</title> <script type="text/javascript" src="APL/NameSpaces.js"></script> <script type="text/javascript" src="Hosting/aplHosting.js"></script> <script type="text/javascript" src="Hosting/apl.js"></script> <script type="text/javascript"> function initAPL() { if (thisAPL == null) { thisAPL = apl.ws() thisAPL(_LIB_["Dates"] + _LIB_["Numbers"]) } } function runMonth(anEvent, aYear, aMonth, anOutput) { if (anEvent == null || anEvent.keyCode == 13) { myArg = aYear.value + " " + aMonth.value if (myArg.trim().length == 0) {return false} myResult = callAPL("month " + myArg) anOutput.value = myResult return false } } function runDay(anEvent, aYear, aMonth, aDay, anOutput) { if (anEvent == null || anEvent.keyCode == 13) { myArg = aYear.value + " " + aMonth.value + " " + aDay.value if (myArg.trim().length == 0) {return false} anOutput.value = callAPL("day " + myArg) return false } } function runRoman(anEvent, isRoman, aNumber, aRoman, anEnglish) { if (anEvent == null || anEvent.keyCode == 13) { if (isRoman) { if (aRoman.value.trim().length == 0) {return false} // NB. fromRoman needs its argument in quotes aNumber.value = callAPL("fromRoman " + quote(aRoman.value)) } else { if (aNumber.value.trim().length == 0) {return false} aRoman.value = callAPL("toRoman " + aNumber.value) } anEnglish.value = callAPL("toEnglish " + aNumber.value) return false } } </script> </head><body onload="handleLoad(formHosting.textYear); initAPL()"> <form name="formHosting" action=""> <table border="0" cellspacing="0" cellpadding="0"> <tr> <td>Year </td> <td>Month</td> <td> Day</td> </tr><tr> <td><input type="Text" name="textYear" size="4" /></td> <td><center><input type="Text" name="textMonth" size="2" onkeypress="return runMonth(event, textYear, textMonth, textCalendar)" /></center></td> <td><center><input type="Text" name="textDay" size="2" onfocus="runMonth(null, textYear, textMonth, textCalendar)" onkeypress="return runDay(event, textYear, textMonth, textDay, textDate)" /></center></td> <td> is a <input type="Text" name="textDate" size="10" onfocus="return runDay(null, textYear, textMonth, textDay, textDate)" readOnly=true /></td> </tr> </table> <br /> <textarea name="textCalendar" rows="8" cols="20" onfocus="showOutput(textOutput)"></textarea><p /> <table border="0" cellspacing="0" cellpadding="0"> <tr> <td>An Integer</td> <td>Roman Numerals</td> </tr><tr> <td><input type="Text" name="textNumber" size="20" onkeypress="return runRoman(event, false, textNumber, textRoman, textEnglish)" /></td> <td><input type="Text" name="textRoman" size="20" onfocus="runRoman(null, false, textNumber, textRoman, textEnglish)" onkeypress="return runRoman(event, true, textNumber, textRoman, textEnglish)" /></td> </tr> </table> <input type="Text" name="textEnglish" size="42" onfocus="runRoman(null, true, textNumber, textRoman, textEnglish)" readOnly=true /><p /> </body></html>
Example APL Code
Here’s an example of the APL code called in the above HTML, from “Namespaces.js”:
_LIB_["Numbers"] = "get_help← {\n (⍪'Functions for displaying numbers:'\n ' toEnglish converts an integer to words' \n ' fromRoman converts a positive integer to Roman Numerals'\n ' toRoman converts from Roman Numerals to a number')\n}\n\nDigits← {\n ⍝ Expand three digits for toEnglish\n Number← 28 9⍴ '_________one______two______three____four_____five_____six______seven____eight____nine_____ten______eleven___twelve___thirteen_fourteen_fifteen__sixteen__seventeeneighteen_ninteen__twenty__-thirty__-forty___-fifty___-sixty___-seventy_-eighty__-ninety__-'\n ∆← ''\n ({⍵← 0 100⊤ ⍵\n ({∆← Number[⍵[0];], ' hundred '\n } ⍣ (⍵[0]≠ 0)) ⍵\n ⍵← ⍵[1]\n ({∆← ∆, ,(Number[18 0+ 10 10⊤ ⍵;])[;(⍳8), (0≠ 10⊤ ⍵)⍴ 8]\n } ⍣ (⍵> 19)) ⍵\n ({∆← ∆, Number[⍵;]\n } ⍣ (⍵< 20)) ⍵\n } ⍣ (⍵≠ 0)) ⍵\n ∆~ '_'\n}\n\ntoEnglish← {\n ⍝ Convert a number into English\n Number← 5 9⍴ 'trillion_billion__million__thousand__________'\n ∆← ({∆← 'zero'} ⍣ (⍵= 0)) ⍵←''⍴ ⍵\n ({∆← (⍵< 0)/ 'negative '\n ⍵← (5⍴ 1000)⊤ |⍵\n now← (⍵≠ 0)⍳ 1\n {∆← ∆, (Digits ⍵) {⍺, (0≠ ⍴⍺)/ ⍵} ' ', Number[now;], ' '\n now← now+ 1\n } ¨ now↓ ⍵\n } ⍣ (⍵≠ 0)) ⍵\n ∆~ '_'\n}\n\nfromRoman← {\n ⍝ Convert from Roman numerals\n ∆← ((14⍴1 5 10 50 100 500 1000), 5000 10000 50000 100000 500000 1000000)['ivxlcdmIVXLCDMⓋⓍⓁⒸⒹⓂ'⍳ ,⍵] ⍝ NB. ()'s currently required\n ∆←∆ +.× ¯1+ 2× ∆≥ 1↓∆, 0\n}\n\ntoRoman← {\n ⍝ Convert a number to Roman numerals\n (⍵< 0)∨ ⍵> 3999 : 'domain error'\n ∆← 4 1 3 2 2 3 1 1 1 2 1 3 1 1 2 1 2 1 1 4 1 2\n ∆←∆/ 2 0 2 0 2 0 2 0 ¯1 2 ¯1 2 ¯1 0 2 ¯1 0 2 ¯1 0 ¯2 2\n ∆←,(10 4 ⍴∆)[(4⍴10)⊤⍵;]\n 'MDCLXVI'[(∆≠2)/∆+2×⌊0.25×⍳16] ⍝ ⓂⒹⒸⓁⓍⓋ\n}\n"