Perkify - REPLs

Written by Rich Morin.

Contents: (hide) (show)

Path:  AreasContentHowTos

Precis:  a quick dip into some Perkify REPLs

A read–eval–print loop (REPL), also termed an interactive toplevel or language shell, is a simple, interactive computer programming environment that takes single user inputs (i.e., single expressions), evaluates (executes) them, and returns the result to the user; a program written in a REPL environment is executed piecewise.

https://en.wikipedia.org/wiki/Read–eval–print_loop

Although REPLs can be used by anyone, the fact that they are text-based and make no use of cursor positioning makes them a particularly good fit for blind users. Some of Perkify’s REPLs are one-trick ponies, good at only one type of task. Others support general-purpose programming languages. That said, let’s dive in…

Note: The following examples do not pretend to display the real capabilities of each command, but they do give the flavor of the language syntax and user interface. (They also show how to escape from the REPL’s clutches!) Rather than printing the full shell prompt (e.g., vagrant@perkify:~$), I just use a dollar sign ($).

Calculators, Math Systems, etc.

These REPLs range from simple (or not so simple) desk calculators to systems for performing algebra, statistics, and more.

bc (bc)

bc is a language that supports arbitrary precision numbers with interactive execution of statements. There are some similarities in the syntax to the C programming language. A standard math library is available by command line option. …

http://manpages.ubuntu.com/manpageseoanman1/bc.1.html

The phrase “arbitrary precision”, in this context, means that numbers can be as large as the computer’s memory can hold. Here’s a bc session that defines and uses a factorial function:

$ bc
...
1 + 2
3
/* Define a factorial function. */
define f(n) {
  if (n <= 1) return 1
  return n * f(n-1)
}
f(42)
1405006117752879898543142606244511569936384000000000
quit
$

calc (calc)

Calc (aka apcalc) is another arbitrary precision calculator. Along with the man page, be sure to check out Landon Curt Noll’s What is calc? page and the files in /usr/share/doc/apcalc/examples.

$ calc
...
; 1 + 2
  3
; fact(42)
  1405006117752879898543142606244511569936384000000000
; 42!
  1405006117752879898543142606244511569936384000000000
; /* Define a factorial function. */
; define f(n) {
;; if (n <= 1) { return 1 }
;; return n * f(n-1)
;; }
f(n) defined
; f(42)
  1405006117752879898543142606244511569936384000000000
; exit
$

JACAL (jacal)

JACAL is a symbolic mathematics system for the simplification and manipulation of equations and single and multiple valued algebraic expressions constructed of numbers, variables, radicals, and algebraic functions, differential, and holonomic functions. In addition, vectors and matrices of the above objects are included.

http://manpages.ubuntu.com/manpageseoanman1/jacal.1.html

Because JACAL is based on scm, it includes a complete Scheme interpreter.

$ jacal
...
e0 : 1 + 2;
e0: 3

e1 : factorial(42);
e1: 1405006117752879898543142606244511569936384000000000

e2 : quit();
$

Octave (octave)

Octave is an interpreted programming language for performing mathematical calculations. Its syntax is reminiscent of MATLAB. For more information, see the GNU Octave and Octave Forge pages.

$ octave
...
octave:1> 1 + 2
ans =  3
octave:2> factorial(42)
ans =    1.4050e+51
octave:3> # Define a factorial function.
octave:3> function r = f(n)
>   if (n <= 1) r = 1;
>   else r = n * f(n-1);
>   endif
> endfunction
octave:4> f(42)
ans =    1.4050e+51
octave:5> ^D
$

R (R)

R is an interpreted programming language for performing statistical computing. Its syntax is reminiscent of S. For more information, see Programming with R.

$ R
...
> 1 + 2
[1] 3
# Define a factorial function.
> f <- function(n) {
+   if (n <= 1) { 1 }
+   else { n * f(n-1) }
+ }
> f(42)
[1] 1.405006e+51
> q()
Save workspace image? [y/n/c]: n
$

units (units)

The “units” program converts quantities expressed in various scales to their equivalents in other scales. The “units” program can handle multiplicative scale changes as well as nonlinear conversions such as Fahrenheit to Celsius. …

http://manpages.ubuntu.com/manpageseoanman1/units.1.html

$ units
...
You have: 100 pound
You want: kilogram
  * 45.359237
  / 0.022046226
You have: 100 degF
You want: degC
  * 55.555556
  / 0.018
You have: 100 mile/hour
You want: furlong/fortnight
  * 268800
  / 3.7202381e-06
You have: quit
$

wcalc (wcalc)

wcalc is a natural-expression command-line calculator. Unlike bc and calc, it uses floating-point arithmetic.

$ wcalc
...
-> 1 + 2
 = 3
-> fact(42)
 = 1.40501e+51
-> ^D
$

Programming Languages

A number of general-purpose programming languages offer REPLs, providing a fast and convenient way to test small bits of code. Perkify has a small sampling of these and may well add more.

Elixir (iex)

Elixir is a strongly-typed functional programming language with syntax that is reminiscent of Ruby. It runs on the Erlang virtual machine.

$ iex
...
iex(1)> 1 + 2
3
iex(2)> # Define a factorial function.
nil
iex(3)> defmodule F do
...(3)>   def f(n) do
...(3)>     if n <= 1 do
...(3)>       1
...(3)>     else
...(3)>       n * f(n-1)
...(3)>     end
...(3)>   end
...(3)> end
{:module, F, ... }
iex(4)> F.f(42)
1405006117752879898543142606244511569936384000000000
iex(5)> ^C
BREAK: (a)bort (c)ontinue (p)roc info ...
a
$

Erlang (erl)

Erlang is a strongly-typed functional programming language with a syntax that is reminiscent of Prolog. It runs on the Erlang virtual machine.

$ erl
...
1> 1 + 2.
3
2> ^C
BREAK: (a)bort (c)ontinue (p)roc info ...
a
$

Forth (gforth)

Forth is an untyped, stack-based language which uses Reverse Polish notation. For more information, see the Gforth Manual.

$ gforth
...
1 2 + CR .
3  ok
\ Define a factorial function.
: f ( n -- n! ) 1 swap 1+ 1 ?do i * loop CR ;  ok
3 f . CR
6
^D
$

Perl (perl)

Perl is a strongly-typed programming language, but it masks this for certain operations (e.g., concatenating a string with an integer). Although Perl does not offer a REPL, per se, its debugger can be used to simulate one:

$ perl -de1
...
main::(-e:1):   1
  DB<1> p 1 + 2
3
  DB<2> p 'abc' . 123
abc123
  DB<3> q
$

Prolog (gprolog)

Prolog is a logic programming language from the Artificial Intelligence community. The full manual for GNU Prolog is available online.

$ gprolog
...
| ?- X is 1 + 2.
X = 3
yes
| ?- ^D
$

Python (ipython, ipython3)

Python is a strongly-typed object-oriented programming language whose syntax uses indentation for program structuring. Perkify offers REPLs for both Python 2 (ipython) and 3 (ipython3).

$ ipython
...
In [1]: 1 + 2
Out[1]: 3

In [2]: # Define a factorial function.

In [3]: def f(n):
   ...:     if n <= 1:
   ...:         return 1
   ...:     else:
   ...:         return n * f(n-1)
   ...:

In [4]: f(42)
Out[4]: 1405006117752879898543142606244511569936384000000000L

In [5]: exit
$

Ruby (irb)

Ruby is a strongly-typed object-oriented programming language.

$ irb
irb(main):001:0> 1 + 2
=> 3
irb(main):002:0> # Define a factorial function.
nil
irb(main):003:0> def f(n)
irb(main):004:1>   n.zero? ? 1 : n * f(n - 1)
irb(main):005:1> end
=> :fact
irb(main):006:0> f(42)
=> 1405006117752879898543142606244511569936384000000000
irb(main):007:0> ^D
$

Scheme (scm)

Scheme is a functional programming language with a parenthesized prefix notation syntax that is reminiscent of Lisp.

$ scm
...
> (+ 1 2)
3
> ; Define a factorial function.
> (define (f n)
>   (if (<= n 0)
>       1
>       (* n (f (- n 1)))))
#<unspecified>
> (f 42)
1405006117752879898543142606244511569936384000000000
> (exit)
;EXIT
$

Tcl (tclsh)

Tcl is an extremely weakly-typed programming language (everything is a string) with somewhat idiosyncratic syntax.

$ tclsh
% puts [expr 1 + 2]
3
% # Define a factorial function.
% proc f n {
    expr {$n < 2 ? 1 : $n * [f [incr n -1]]}
}
% puts [f 42]
1405006117752879898543142606244511569936384000000000
% exit
$

Shells (e.g., bash)

John D. Cook makes some interesting points about shells and REPLs:

A shell is not the same as a REPL (Read Evaluate Print Loop). They look similar, but they have deep differences.

Shells are designed for one-line commands, and they’re a little awkward when used as programming languages.

Scripting languages are designed for files of commands, and they’re a little awkward to use from a REPL.

IPython is an interesting hybrid. You could think of it as a Python REPL with shell-like features added. Eshell is another interesting compromise, a shell implemented in Emacs Lisp that also works as a Lisp REPL. These hybrids are evidence that as much as people like their programming languages, they appreciate additions to a pure language REPL.

Shell != REPL

However, using a shell interactively is a lot like using a REPL. Here’s an example in Bash; you decide…

$ echo $((1 + 2))
3
$

To be continued…