Language history: origin of variable 'it' in read-eval-print loop? - programming-languages

Some interactive systems, including Standard ML of New Jersey and GHC, offer an interactive toplevel loop where you can type expressions and see results. A nice little convenience is that the result of the most recent expression is bound to the variable it. Here's an example from GHCi:
Prelude> 3 + 5
8
Prelude> it
8
Prelude> 2 * it
16
Prelude> it + 1
17
I'm trying to trace the origin of this convention. Can anyone provide examples of other interactive systems that have used similar conventions? And date them if possible?

Ruby provides the same convenience variable as _:
>> 3 + 5
=> 8
>> _
=> 8
>> 2 * _
=> 16
>> _ + 1
=> 17
Interestingly, the global variable $_ is also available: it's the last input read from gets or readline.

Many common lisps use '*' to denote previous results. EG '*' is the last result, '**' is the result before last, etc:
* 5
5
* 6
6
* 7
7
* (+ * ** ***)
18
Python has '_' which is last result:
>>> 5
5
>>> _
5
Erlang has a function 'v()':
1> 5.
5
2> 6.
6
3> 7.
7
4> v(1) + v(2) + v(3).
18

Not a REPL, but hypertalk (the language of hypercard) allowed "it" in some contexts. I'm not sure of the exact usage case, as I never used hypercard, but it appears to be a similar idea. This dates it to 1986 or so.

It seems that the first instance of a REPL with history list functionality was BBN LISP, ca. 1972.
"In BBN-LISP, each input typed by the user, and the value of the corresponding operation, are automatically stored by the p.a. on a global data structure called the history list." I could not find any documentation on how to actually access those values, only on how to repeat previous events using REDO. (See http://www.softwarepreservation.org/projects/LISP/interlisp/Teitelman-FCJJ1972.pdf)
Nor could I find any single keyword for accessing the last history value in its successor Interlisp, possibly due to lack of Google-Fu.

Related

Reassignment in ghci

Is it possible to reassign the same variable in ghci ? Of course this isn't possible in normal Haskell (at least without something like an IORef), but I was curious because the it variable in ghci that you get by enabling the :m option. With that enabled I get an experience where it is effectively reassignable by not binding the next expression to anything, e.g.
λ> 1 + 1
2
it :: Num a => a
λ> it
2
it :: Num a => a
λ> it + 1
3
it :: Num a => a
λ> it
3
it :: Num a => a
Is there a way to realize the same effect for an arbitrary named variable, not just the special it ?
Each new line in GHCi enters new, nested scope. Consider
> x = 1
> x
1
> foo y = x + y
> foo 41
42
> x = 7 -- new x
> x
7
> bar y = x + y -- refers to new x
> bar 41
48
> foo 41 -- still refers to the same old x binding
42
Second binding of x defines new same-named variable.
Naturally, it shadows the previous binding for that name, making it inaccessible in itself. Any other entity (like foo) which referenced it before though, will continue to hold that reference, no matter the shadowing for the newer, nested environments.
This follows the principle of immutability of values in Haskell: the foo remains the same.
One caveat:
> :{
x = 1
foo y = x + y
x = 7 -- error: conflicting definition
bar y = x + y
:}
causes an error, because lines entered in multiline mode belong to the same scope.
In other words the answer to your question is no, it would break the fundamental purity properties of Haskell.
it is not reassigned either, it is defined anew in each new nested environment, whenever there is any output, being bound to the output value:
> x
7
> it
7
> it_2 -- made a typo
error: Not in scope: `it_2'
> it+2 -- no previous output, same `it` in effect
9
> it+2 -- most recent `it` is 9
11
So you can always shadow your variable and create a new binding with the same name, but you can't change the old binding, because it is a part of history now, and the past can not be changed, by definition. It already happened.
Or you could create your own Haskell interpreter where you'd give a user an ability to "change" an old binding, but what would really happen is that a new copy of the interpreter would be spawned even "playing" all the recorded user actions at the prompt -- new definitions and all -- from that point on. Then the user would end up with a changed copy which would be oblivious to the existence of the first one. You could even kill the original at that point. Could this be considered as user having changed the past? The user's past hasn't changed, their time goes forward. The new copy's past was always what it is now, as far as it is concerned. The older original (copy?) is gone... A question to ponder.

How to count each list length in K?

On a page https://shakti.com/tutorial/ I've found the solution, it is
#:'z / counts each list
The same solution was mentioned in https://code.kx.com/v2/learn/startingkdb/language/ by switching to k mode in q:
q) #:'(1 2;"abc") / equivalent k expression
2 3
Why this expression #:' counts the number?
# counts
' is an each Adverb
but what : means in this case? This is not an assignment, right?
On a page http://www.math.bas.bg/bantchev/place/k.html they mentioned that:
: within |: is used to force the verb | to be interpreted as a monad,
as by default ambiguities are resolved in favour of dyads
Also here http://web.archive.org/web/20050504070651/http://www.kx.com/technical/documents/kreflite.pdf noted about the same:
Note that whenever Each is applied to the monad of a primitive verb,
as in !:' for Enumerate-Each, the monadic case must be made explicit
by modifying the verb with colon. The dyadic case is assumed if no
modifier is present.
And that's make sense:
/ # want's to act as dyadic verb
#' (1 2; "abc")
#'[(1 2;"abc")]
/ make use of dyadic # behavior
5 6 #' (1 2; "abc")
(1 2 1 2 1;"abcabc")
/ monadic case
#:' (1 2; "abc")
2 3

Can I introspect a variable to directly discover what subset it was declared with?

Is there a way to introspect a variable to directly find out what subset it was declared with? Here I create a subset, but introspection points me to its base type:
> subset Prime of Int where .is-prime
(Prime)
> my Prime $x = 23
23
> $x.WHICH
Int|23
I know it has to store the information somewhere, because if I try to reassign a value that doesn't match the subset, it fails:
> $x = 24
Type check failed in assignment to $x; expected Prime but got Int (24)
in block <unit> at <unknown file> line 1
I tried searching through the code, but I quickly get down into files like container.c and perl6_ops.c where the C code makes my eyes glaze over. I thought that X::TypeCheck::Assignment might help (see core/Exception.pm), but it's not clear to me where the expected value comes from. (see also this commit)
I feel like I'm missing something obvious.
I can check that something matches a subset, but that doesn't tell me if it were declared with a particular subset:
> my Int $y = 43;
43
> $y ~~ Prime;
True
I'm using Rakudo Star 2017.01
Inspired by a Zoffix's use of subsets in a recent post.
The value that you stored in $x is an Int. It is acceptable to the container (which you typed to Prime) because Prime is a subtype of Int.
So what you're interested in, is not the value in the container, but the type of the container. To get at the container, Perl 6 has the .VAR method. And that has an .of method to get at the type:
$ 6 'subset Prime of Int where .is-prime; my Prime $x; dd $x.VAR.of'
Prime

Nested explicit definitions

For the sake of argument, let's say I want the following program:
foo =: monad define
bar =. dyad define
x * y
)
bar/ y * 2 3
)
Ideally, for input 3, this would yield 54. However, when putting this into the console, the first of the two )s is treated as the ending for the first define. Is there any way to prevent this? I want to avoid an inline verb, like monad def 'x * y'. My actual verb example is more complex than this.
You can not have nested multiline definitions as there is no check for the contents of the definition. The definition ends and saved on the first encounter of ^)LF.
a multiline body is a script terminated by a solo right parenthesis, so we cannot have one such body inside another.
There are (messy) ways to go around this, for example by forming strings and evaluating them:
foo =: monad define
str =. 'x * y'
bar =. 4 : (str,:'')
bar /y * 2 3
)
foo 3
54
Maybe forming a helper adverb is a better idea.
(edit) Example by defining bar's body separately:
bar_body =: 0 : 0
c=. x + y
c * y
)
foo =: 3 : 0
bar =. 4 : bar_body
bar/y * 2 3
)
foo 3
135
The nested terminating ')'s are problematic, but this could work
foo =: monad define
bar =. 4 : 'x * y'
bar/ y * 2 3
)
foo 3
54
Multiple lines in bar definition could just be consecutive boxed
strings.
foo =: monad define
bar =. 4 : ('t=.x * y';'t+1') NB. parenthesis required
bar/ y * 2 3
)
foo 3
55
The absence of nested blocks was an intentional design decision.
The idea is to put pressure on the developer to name blocks. (And, more generally, there's some significant pressure on the developer to favor concise, simple code.)
That said, adverbs (and conjunctions) can be used to tie blocks together.

Fortran runtime error "bad integer for item 11 in list input"

I receive the runtime error "bad integer for item 11 in list input" referencing the following line of code.
read(2,*)a,b,c,d,e,f,g,h,theta1,phi1,k,l,m,n,o,
$ p,theta2,phi2,s,theta3,phi3,
$ r1,x1,y1,r2,x2,y2,r3,x3,y3,z1,z2,z3
The line its reading from is
1 255.11211 0.2876 165.11404 90 4 8 0.19173 90 165.11404 0.09587 90 345.11404 4 4 0.0764 89.99915 -64.51149 0.11131 90.0015 24.23892 470.10565 -454.32263 120.7902 264.91144 114.00389 -239.12589 322.2894 293.87778 132.3114 0.01236 0.00697 0.00006 0.42619 -0.19278
so a mix of integers and reals, but I thought this was okay since I used the * format descriptor rather than a specified format.
I'm using the gcc compiler.
Item 11 in your list is 0.09587, a real. You are using list directed input, which for a real is interpreted a numeric value using an F edit descriptor (Fortran 2008 Cl. 10.10.3 paragraph 4). An input list item corresponding to an F edit descriptor must be real or complex (Fortran 2008 Cl. 10.7.2.3.1 paragraph 1).
To fix this you need to define k as a real variable. You note in a comment that you are using implicit typing (where variables starting with i-n are integer types and the rest are real by default). To explicitly declare k as a real, use:
real :: k
Best practices are to disable implicit typing (implicit none) and explicitly type all of your variables.

Resources