數字派 NumPy ︰陣列運算‧《外傳二》APL ㄆ

A 起頭的『高階』程式語言 APL 太過先進乎?所以一行就能得 1 \dots R 內之質數呦。

Prime numbers

The following expression finds all prime numbers from 1 to R. In both time and space, the calculation complexity is \displaystyle O(R^{2})\,\! (in Big O notation).

(~R∊R∘.×R)/R←1↓ιR

Executed from right to left, this means:

  • Iota ι creates a vector containing integers from 1 to R (if R= 6 at the start of the program, ιR is 1 2 3 4 5 6)
  • Drop first element of this vector ( function), i.e., 1. So 1↓ιR is 2 3 4 5 6
  • Set R to the new vector (, assignment primitive), i.e., 2 3 4 5 6
  • The / reduction operator is dyadic (binary) and the interpreter first evaluates its left argument (fully in parentheses):
  • Generate outer product of R multiplied by R, i.e., a matrix that is the multiplication table of R by R (°.× operator), i.e.,
4 6 8 10 12
6 9 12 15 18
8 12 16 20 24
10 15 20 25 30
12 18 24 30 36
  • Build a vector the same length as R with 1 in each place where the corresponding number in R is in the outer product matrix (, set inclusion or element of or Epsilon operator), i.e., 0 0 1 0 1
  • Logically negate (not) values in the vector (change zeros to ones and ones to zeros) (, logical not or Tilde operator), i.e., 1 1 0 1 0
  • Select the items in R for which the corresponding element is 1 (/ reduction operator), i.e., 2 3 5

(Note, this assumes the APL origin is 1, i.e., indices start with 1. APL can be set to use 0 as the origin, so that ι6 is 0 1 2 3 4 5, which is convenient for some calculations.)

 

即使有人分解的說,概念貫串彷彿似『低階』組合語言,尚須細思慢嚼,要不易墬五里霧中裡。因此學習才需要天賦耶?

想那 2 \dots R 之自然數,可為質數或合成數。若 n = p \times q, \ p,q \ge 2, n \le R ,則

n \in R \circ . \times R 也。

故而一『否定』~ 再加上一『對應選擇』/足矣!

一時腦海迴盪著當年驚訝之事

沒有 if 以及 loop 語法結構,該如何寫程式ㄚ?

歡迎翱翔另類思考天空◎

APL (programming language)

APL (named after the book A Programming Language)[2] is a programming language developed in the 1960s by Kenneth E. Iverson. Its central datatype is the multidimensional array. It uses a large range of special graphic symbols[3] to represent most functions and operators, leading to very concise code. It has been an important influence on the development of concept modeling, spreadsheets, functional programming,[4] and computer math packages.[5] It has also inspired several other programming languages.[6][7]

Language characteristics

Character set

APL has been both criticized and praised for its choice of a unique, non-standard character set. Some who learn it become ardent adherents, suggesting that there is some weight behind Iverson’s idea that the notation used does make a difference. In the 1960s and 1970s, few terminal devices and even display monitors could reproduce the APL character set. The most popular ones employed the IBM Selectric print mechanism used with a special APL type element. One of the early APL line terminals (line-mode operation only,not full screen) was the Texas Instruments TI Model 745 (circa 1977) with the full APL character set[42] which featured half and full duplex telecommunications modes, for interacting with an APL time-sharing service or remote mainframe to run a remote computer job,called an RJE.

Over time, with the universal use of high-quality graphic displays, printing devices and Unicode support, the APL character font problem has largely been eliminated. However, entering APL characters requires the use of input method editors, keyboard mappings, virtual/on-screen APL symbol sets,[43][44] or easy-reference printed keyboard cards which can frustrate beginners accustomed to other programming languages.[45][46][47] With beginners who have no prior experience with other programming languages, a study involving high school students found that typing and using APL characters did not hinder the students in any measurable way.[48]

In defense of APL use, APL requires less coding to type in, and keyboard mappings become memorized over time. Also, special APL keyboards are manufactured and in use today, as are freely available downloadable fonts for operating systems such as Microsoft Windows.[49] The reported productivity gains assume that one will spend enough time working in APL to make it worthwhile to memorize the symbols, their semantics, and keyboard mappings, not to mention a substantial number of idioms for common tasks.[citation needed]

Design

Unlike traditionally structured programming languages, APL code is typically structured as chains of monadic or dyadic functions, and operators[50] acting on arrays.[51] APL has many nonstandard primitives (functions and operators) that are indicated by a single symbol or a combination of a few symbols. All primitives are defined to have the same precedence, and always associate to the right. Thus, APL is read or best understood from right-to-left.

Early APL implementations (circa 1970 or so) had no programming loop-flow control structures, such as do or while loops, and if-then-else constructs. Instead, they used array operations, and use of structured programming constructs was often not necessary, since an operation could be performed on a full array in one statement. For example, the iota function (ι) can replace for-loop iteration: ιN when applied to a scalar positive integer yields a one-dimensional array (vector), 1 2 3 … N. More recent implementations of APL generally include comprehensive control structures, so that data structure and program control flow can be clearly and cleanly separated.

The APL environment is called a workspace. In a workspace the user can define programs and data, i.e., the data values exist also outside the programs, and the user can also manipulate the data without having to define a program.[52] In the examples below, the APL interpreter first types six spaces before awaiting the user’s input. Its own output starts in column one.

……

Flow control

A user may define custom functions which, like variables, are identified by name rather than by a non-textual symbol. The function header defines whether a custom function is niladic (no arguments), monadic (one right argument) or dyadic (left and right arguments), the local name of the result (to the left of the ← assign arrow), and whether it has any local variables (each separated by semicolon ‘;’).

Whether functions with the same identifier but different adicity are distinct is implementation-defined. If allowed, then a function CURVEAREA could be defined twice to replace both monadic CIRCLEAREA and dyadic SEGMENTAREA above, with the monadic or dyadic function being selected by the context in which it was referenced.

Custom dyadic functions may usually be applied to parameters with the same conventions as built-in functions, i.e., arrays should either have the same number of elements or one of them should have a single element which is extended. There are exceptions to this, for example a function to convert pre-decimal UK currency to dollars would expect to take a parameter with precisely three elements representing pounds, shillings and pence.[11]

Inside a program or a custom function, control may be conditionally transferred to a statement identified by a line number or explicit label; if the target is 0 (zero) this terminates the program or returns to a function’s caller. The most common form uses the APL compression function, as in the template (condition)/target which has the effect of evaluating the condition to 0 (false) or 1 (true) and then using that to mask the target (if the condition is false it is ignored, if true it is left alone so control is transferred).

Hence function SEGMENTAREA may be modified to abort (just below), returning zero if the parameters (DEGREES and RADIUS below) are of different sign:

∇ AREA←DEGREES SEGMENTAREA RADIUS ; FRACTION ; CA ; SIGN     ⍝ local variables denoted by semicolon(;)
  FRACTION←DEGREES÷360
  CA←CIRCLEAREA RADIUS        ⍝ this APL code statement calls user function CIRCLEAREA, defined up above.
  SIGN←(×DEGREES)≠×RADIUS     ⍝ << APL logic TEST/determine whether DEGREES and RADIUS do NOT (≠ used) have same SIGN 1-yes different(≠), 0-no(same sign)
  AREA←0                      ⍝ default value of AREA set = zero
  →SIGN/0                     ⍝ branching(here, exiting) occurs when SIGN=1 while SIGN=0 does NOT branch to 0.  Branching to 0 exits function.
  AREA←FRACTION×CA
∇

The above function SEGMENTAREA works as expected if the parameters are scalars or single-element arrays, but not if they are multiple-element arrays since the condition ends up being based on a single element of the SIGN array – on the other hand, the user function could be modified to correctly handle vectorized arguments. Operation can sometimes be unpredictable since APL defines that computers with vector-processing capabilities should parallelise and may reorder array operations as far as possible – thus, test and debug user functions particularly if they will be used with vector or even matrix arguments. This affects not only explicit application of a custom function to arrays, but also its use anywhere that a dyadic function may reasonably be used such as in generation of a table of results:

        90 180 270 ¯90 ∘.SEGMENTAREA 1 ¯2 4
0 0 0
0 0 0
0 0 0
0 0 0

A more concise way and sometimes better way – to formulate a function is to avoid explicit transfers of control, instead using expressions which evaluate correctly in all or the expected conditions. Sometimes it is correct to let a function fail when one or both input arguments are incorrect – precisely to let user know that one or both arguments used were incorrect. The following is more concise than the above SEGMENTAREA function. The below importantly correctly handles vectorized arguments:

 ∇ AREA←DEGREES SEGMENTAREA RADIUS ; FRACTION ; CA ; SIGN
   FRACTION←DEGREES÷360
   CA←CIRCLEAREA RADIUS
   SIGN←(×DEGREES)≠×RADIUS
   AREA←FRACTION×CA×~SIGN  ⍝ this APL statement is more complex, as a one-liner - but it solves vectorized arguments: a tradeoff - complexity vs. branching
 ∇

        90 180 270 ¯90 ∘.SEGMENTAREA 1 ¯2 4
0.785398163 0           12.5663706
1.57079633  0           25.1327412
2.35619449  0           37.6991118
0           ¯3.14159265 0

Avoiding explicit transfers of control also called branching, if not reviewed or carefully controlled – can promote use of excessively complex one liners, veritably “misunderstood and complex idioms” and a “write-only” style, which has done little to endear APL to influential commentators such as Edsger Dijkstra.[12] Conversely however APL idioms can be fun, educational and useful – if used with helpful comments ⍝, for example including source and intended meaning and function of the idiom(s). Here is an APL idioms list, an IBM APL2 idioms list here[13] and Finnish APL idiom library here.

………