├── README.md ├── LICENSE ├── Parallel ├── README.md ├── IIX.dyalog └── IIPageStats.dyalog └── HTMLRenderer └── WebSocketSample.dyalog /README.md: -------------------------------------------------------------------------------- 1 | Samples 2 | ======= 3 | 4 | This repository contains code samples and templates that are referenced by Dyalog documentation, web pages and blogs, etc. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Dyalog Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Parallel/README.md: -------------------------------------------------------------------------------- 1 | Dyalog/Samples/Parallel 2 | ======================= 3 | 4 | This folder contains code samples which illustrate the use of Futures and Isolates. 5 | 6 | File |Fn/Op/etc |Comments | 7 | ------------------|-----------|---------------------| 8 | IIX.dyalog |PEACH |Cover for IÏX which optimises use of isolates and optionally displays a progress bar| 9 | IIPageStats.Dyalog|Report |Example which uses IIX.PEACH to analyse a large number of web pages| 10 | 11 | IIX.PEACH 12 | --------- 13 | `[left] (function[[callback][cblarg]] IIX.PEACH isolates) right` 14 | 15 | Compared to the standard `IÏX` operator, `IIX.PEACH` provides functionality similar to that provided by the old `PEACH` operator from the experimental "parallel" workspace: 16 | 17 | 1. Instead of creating a new isolate for each function call, `IIX.PEACH` [re]uses a set of isolates, feeding each one another function call when it completes the preceeding one. 18 | 2. An optional callback function can be provided, it will be called each time a new function call is dispatched. 19 | 3. A default callback mechanism is provided, which displays a form with progress bars. 20 | 21 | Arg/Operand | Example | Description | 22 | --------------|--------------|----------------------| 23 | left, right | | operand arguments. | 24 | function | 'foo' | Must be a quoted character vector. 25 | callback | 'cb' | Right argument will be a count of calls completed per isolate, plus the total number of calls started. Pass an empty vector ('') to get the progress form. The callback function should return 0 if all is OK, or 1 to abort the current process. The default version returns 1 if the progress form is closed.| 26 | cblarg | 'Hello' | Optional left argument to the callback function. If you use the default progress form, the value will be used as the caption.| 27 | isolates | ''
ns
isolates | Empty vector to create (≢processors) empty isolates
Scalar namespace to create (≢processors) clones of ns
or: a Vector of pre-created isolates| 28 | 29 | IIPageStats.Report 30 | ------------------ 31 | The "Report" function is intended as a simple but realistic example of the use of isolates via IIX.PEACH: The function takes a 2-letter US state code as the right argument, and returns a 2-column matrix with letter frequency counts from the front page of all major newspapers in that state. For example: 32 | ``` 33 | IIPageStats.Report 'al' 34 | E 94540 35 | T 73232 36 | A 66385 37 | ...down to... 38 | J 4225 39 | Q 2216 40 | Z 1143 41 | ``` 42 | 43 | The function uses The US Newspaper List (http://USNPL-com) to find a list of major newspapers in the state named in the right argument. It then uses IIX.PEACH to process the the newspapers in parallel, using the default progress dialog so that you can track the progress visually. 44 | 45 | An optional left argument allows you to set the number of isolates to use. Since these tasks ar highly I/O bound, it can be advantageous to run with a much higher number of isolates than the number of cores that is available on the machine - try 10 or 20, for example. 46 | 47 | > Written with [StackEdit](https://stackedit.io/). 48 | -------------------------------------------------------------------------------- /Parallel/IIX.dyalog: -------------------------------------------------------------------------------- 1 | :Namespace IIX 2 | ⍝ Parallel Extensions. 3 | 4 | ∇ r←{left}(fns PEACH iss)right;dyadic;fn;cb;n;counts;shape;ni;i;count;done;failed;next;run1iso;callbk;expr;z;PF;cblarg;cancelled 5 | ⍝ IÏ using persistent Isolates: 6 | ⍝ 7 | ⍝ iss is a list of refs to pre-existing isolates to use 8 | ⍝ or if scalar, processors×processes clones will be made 9 | ⍝ 10 | ⍝ fns is either: 11 | ⍝ a simple char vec name of function expected to be in supplied isolates 12 | ⍝ a nested vec of two fn names, in which case 2nd name is a progress callback 13 | ⍝ use empty callback fn for default display 14 | 15 | :If dyadic←2=⎕NC'left' ⍝ Scalar extension 16 | :If 1=×/⍴left ⋄ left←(⍴right)⍴left 17 | :ElseIf 1=×/⍴right ⋄ right←(⍴left)⍴right 18 | :EndIf 19 | :EndIf 20 | 21 | :If 0=≢iss ⋄ iss←⊂'' ⋄ :EndIf 22 | :If 0=⍴⍴iss ⍝ If scalar, clone 23 | iss←#.isolate.{New¨(×/Config¨'processors' 'processes')⍴⍵}iss 24 | :EndIf 25 | 26 | :If 2=≡fns ⍝ We have a callback function 27 | (fn cb cblarg)←3↑fns,'' '' 28 | cblarg,←(0=≢cblarg)/'IIX.PEACH Progress - ',fn,' (',(⍕×/⍴right),')' 29 | :If 0=⍴cb ⍝ Default Progress Form 30 | :If PEACHForm cblarg(≢iss)(×/⍴right) 31 | cb←'PEACHUpdate' 32 | :EndIf 33 | :EndIf ⍝ Default 34 | :Else ⋄ fn←fns ⋄ cb←'⊣' ⋄ :EndIf 35 | 36 | callbk←⍎cb 37 | 38 | ni←≢iss 39 | shape←⍴right 40 | n←⍴right←,right ⋄ :If dyadic ⋄ left←,left ⋄ :EndIf 41 | counts←ni⍴0 ⋄ done←failed←n⍴count←0 42 | r←n⍴⎕NULL 43 | 44 | run1iso←{⍝ drive isolate ⍵ until we are done 45 | n 8 | ⍝ 9 | ⍝ 10 | ⍝ 11 | ⍝ WebSocket Sample 12 | ⍝ 107 | ⍝ 116 | ⍝ 117 | ⍝ 118 | ⍝ 119 | ⍝
120 | ⍝

WebSocket Sample

121 | ⍝ 122 | ⍝
123 | ⍝ 124 | ⍝ 125 | ⍝ 126 | ⍝    127 | ⍝    128 | ⍝
129 | ⍝
130 | ⍝ 140 | ⍝ 141 | ⍝
142 | ⍝
143 | ⍝ 144 | ⍝ 145 | EndHTML: 146 | html←'HTML'(1↓∊(⎕UCS 13),¨{⍵↓⍨⍵⍳'⍝'}¨StartHTML↓EndHTML↑⎕NR fn←⊃⎕XSI) 147 | :If 0∊⍴args 148 | 'hr'⎕WC'HTMLRenderer'html('Event' 'All'fn)('InterceptedURLs'(1 2⍴'ws://dyalog_root/' 1)) 149 | hr.ShowDevTools 1 150 | :Else 151 | :Select 2⊃args 152 | :Case 'WebSocketUpgrade' 153 | ⎕←'obj ev wsid url hdr auto'show args 154 | (obj ev wsid url)←4↑args 155 | resp←args 156 | StartCode:→EndCode 157 | ⍝ Send parms;msg;type;segs 158 | ⍝ ⍝ send data to currently open HTMLRenderer/websocket 159 | ⍝ ⍝ parms [1] msg [2] datatype (1-text, 2-bin) 160 | ⍝ (msg type)←'' 0{(≢⍺)↑⍵,(≢⍵)↓⍺},⊆parms 161 | ⍝ 2 ⎕NQ _hr 'WebSocketSend' _wsid msg 1 ((1+type=0)⊃type,1+(⎕DR'')≠⎕DR msg) 162 | EndCode: ' function defined',⍨⎕FX('_hr' '_wsid'⎕R('''',obj,'''')('''',wsid,'''')){⍵↓⍨⍵⍳'⍝'}¨(1+StartCode)↓EndCode↑⎕NR fn 163 | 164 | :Case 'WebSocketReceive' 165 | ⎕←'obj ev wsid data type fin'show args 166 | (obj ev wsid data type fin)←args 167 | 168 | :Case 'WebSocketClose' 169 | ⎕←'obj ev wsid code reason'show args 170 | (obj ev wsid code reason)←args 171 | 172 | :Case 'WebSocketError' 173 | ⎕←'obj ev wsid'show args 174 | :EndSelect 175 | :EndIf 176 | -------------------------------------------------------------------------------- /Parallel/IIPageStats.dyalog: -------------------------------------------------------------------------------- 1 | :Namespace IIPageStats 2 | ⍝ Future/Isolate code sample, using #.IIX.PEACH 3 | ⍝ Report 'al' 4 | ⍝ ... to get a letter frequency count for home pages of newspapers in Alabama 5 | 6 | (⎕IO ⎕ML)←1 7 | alphabet←'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' 8 | 9 | ∇ freq←{nprocs}Report state;pages;html;cap;PF;AI3;iss 10 | AI3←⎕AI[3] 11 | 12 | :If 0=⎕NC'nprocs' ⋄ nprocs←#.isolate.Config'processors' ⋄ :EndIf ⍝ Default to use all processors 13 | iss←#.ø¨nprocs⍴⎕THIS ⍝ Make isolates 14 | 15 | pages←PapersInState state 16 | cap←'Processing ',(⍕≢pages),' major papers in state "',state,'"' 17 | freq←('CountPageChars' ''cap #.IIX.PEACH iss)pages 18 | freq←⊃+/freq 19 | freq←(26↑alphabet),⍪+⌿2 26⍴freq 20 | freq←freq[⍒freq[;2];] 21 | 22 | ⎕←'Elapsed seconds for ',state,': ',1⍕⎕AI[3]-AI3 23 | ∇ 24 | 25 | ∇ pages←PapersInState state;text;ignore;txt 26 | ⍝ Retrieve list of home pages of major newspapers in named state 27 | ⍝ Thanks to USNPL.com - the US NewsPaper List 28 | 29 | text←GetPage'http://www.usnpl.com/',state,'news.php' 30 | 31 | ⍝ ↓↓↓ extract the body containing newpaper page links 32 | txt←(('for address downloads.'⍷text)⍳1)↓text 33 | txt←(5+(''⍷txt)⍳1)↓txt 34 | txt←(¯1+(''⍷txt)⍳1)↑txt 35 | 36 | pages←('()'⎕S'\2.com/')txt ⍝ All href's to a .com 37 | ∇ 38 | 39 | ∇ r←CountPageChars url;text;html 40 | ⍝ Return letter frequency count for a URL 41 | 42 | html←{0::'' ⋄ GetPage ⍵}url 43 | text←('<.*?>'⎕R'')html ⍝ Remove all (well, lots of) HTML tags 44 | text←(text∊alphabet)/text ⍝ Remove all irrelevant chars 45 | r←¯1+{≢⍵}⌸alphabet,text ⍝ Frequency count 46 | ∇ 47 | 48 | :Section HTTP Tools 49 | 50 | ∇ r←GetPage url;headers;rc;z 51 | ⍝ Get an HTTP page - throw any errors using ⎕SIGNAL 52 | →(0=1⊃(rc headers r)←3↑z←HTTPGet url)⍴0 53 | (⍕z)⎕SIGNAL 11 54 | ∇ 55 | 56 | ∇ r←{certs}HTTPGet url;U;DRC;protocol;wr;key;flags;pars;secure;data;z;header;datalen;host;port;done;cmd;b;page;auth;p;x509;priority;err;req;fromutf8;chunked;chunk;h2d;buffer;chunklength;len;getchunklen;m;split;NL;ws 57 | ⍝ Copied from CONGA workspace Samples namespace 58 | ⍝ Get an HTTP page, format [HTTP[S]://][user:pass@]url[:port][/page] 59 | ⍝ Opional Left argument: PublicCert PrivateKey SSLValidation 60 | ⍝ Makes secure connection if left arg provided or URL begins with https: 61 | 62 | ⍝ Result: (return code) (HTTP headers) (HTTP body) [PeerCert if secure] 63 | 64 | ⍝ ↓↓↓ This is not in the original CONGA sample 65 | ⍝ ↓↓↓ Replace when CONGA sample updated 66 | :If 0∊m←#.⎕NC z←'HTTPUtils' 'DRC' 67 | ws←(2 ⎕NQ'.' 'GetEnvironment' 'dyalog'),'/WS/conga' 68 | (↑(m=0)/z)#.⎕CY ws 69 | :EndIf 70 | 71 | (U DRC)←#.(HTTPUtils DRC) ⍝ Uses utils from here 72 | fromutf8←{0::(⎕AV,'?')[⎕AVU⍳⍵] ⋄ 'UTF-8'⎕UCS ⍵} ⍝ Turn raw UTF-8 input into text 73 | h2d←{⎕IO←0 ⋄ 16⊥'0123456789abcdef'⍳U.lc ⍵} ⍝ hex to decimal 74 | getchunklen←{¯1=len←¯1+⊃(NL⍷⍵)/⍳⍴⍵:¯1 ¯1 ⋄ chunklen←h2d len↑⍵ ⋄ (⍴⍵)0 150 | done←done∨datalen≤⍴data ⍝ ... or if declared amount of data rcvd 151 | :Else 152 | done←done∨(∨/''⍷data)∨(∨/''⍷data) 153 | :EndIf 154 | :EndIf 155 | :EndIf 156 | :Until done 157 | 158 | :Trap 0 ⍝ If any errors occur, abandon conversion 159 | :If ∨/'deflate'⍷(2⊃header)U.GetValue'content-encoding' '' ⍝ was the response compressed? 160 | data←fromutf8 DRC.flate.Inflate 120 156,256|83 ⎕DR data ⍝ append 120 156 signature because web servers strip it out due to IE 161 | :ElseIf ∨/'charset=utf-8'⍷(2⊃header)U.GetValue'content-type' '' 162 | data←'UTF-8'⎕UCS ⎕UCS data ⍝ Convert from UTF-8 163 | :EndIf 164 | :EndTrap 165 | 166 | :If {(⍵[3]∊'12357')∧'30 '≡⍵[1 2 4]}4↑{⍵↓⍨⍵⍳' '}(⊂1 1)⊃2⊃header ⍝ redirected? (HTTP status codes 301, 302, 303, 305, 307) 167 | →GET⍴⍨0<⍴url←'location'{(⍵[;1]⍳⊂⍺)⊃⍵[;2],⊂''}2⊃header ⍝ use the "location" header field for the URL 168 | :EndIf 169 | 170 | r←(1⊃wr)(2⊃header)data 171 | 172 | :If secure ⋄ r←r,⊂DRC.GetProp cmd'PeerCert' ⋄ :EndIf 173 | :Else 174 | 'Connection failed ',,⍕r 175 | :EndIf 176 | 177 | z←DRC.Close cmd 178 | ∇ 179 | 180 | :EndSection ⍝ HTTP Tools 181 | 182 | :EndNamespace --------------------------------------------------------------------------------