Topic variable: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Standard ML}}: Made SML entry more precise and added example)
Line 212: Line 212:


=={{header|Standard ML}}==
=={{header|Standard ML}}==
The SML language itself does not define a topic variable, but interactive implementations may define their own.
If an SML expression is evaluated interactively (that is, the fragment of program provided interactively is an expression and not a variable initialization), the value of the expression is used to initialize a variable, <tt>it</tt>. This is a feature of the interactive shell only.
For example the SML/NJ REPL defines a topic variable named <tt>it</tt> which is bound any time the user types an
{{incomplete|Standard ML|Actually need to do the details of the task, and not just talk about it.}}
expression in the REPL (as opposed to a declaration).

<lang sml>- 3.0;
val it = 3.0 : real
- it * it;
val it = 9.0 : real
- Math.sqrt it;
val it = 3.0 : real
-</lang>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==

Revision as of 17:13, 5 May 2014

Task
Topic variable
You are encouraged to solve this task according to the task description, using any language you may know.

Several programming languages offer syntax shortcuts to deal with the notion of "current" or "topic" variable. A topic variable is a special variable with a very short name which can also often be omitted.

Demonstrate the utilization and behaviour of the topic variable within the language and explain or demonstrate how the topic variable behaves under different levels of nesting or scope, if this applies, within the language.

For instance you can (but you don't have to) show how the topic variable can be used by assigning the number to it and then computing its square and square root.

Erlang

There are no global variables, so Erlang uses a function, v(N), to get old results. Either the absolute command result, if N is positive, or, if N is negative, the return value of the Nth previous command.

Output:
7> 1 + 2.
3
8> v(-1).
3

Forth

In a stack oriented language like Forth the definition of variables is minimized as much as possible. The closest thing to a topic variable is the use of R@. This gets the top item from the return stack, which by the way is also used for flow control. It is up to the programmer to keep the stack balanced. In some Forth dialects R@ and I are identical. I is used as a loop index, e.g.

<lang forth>: myloop 11 1 do i . loop cr ; myloop</lang>

Which will print all numbers from 1 to 10. A typical use of R@ is illustrated here:

<lang forth>: ^2 dup * ;

sqrt 0 tuck ?do 1+ dup 2* 1+ +loop ;
topic >r r@ ^2 . r@ sqrt . r> drop ;

23 topic</lang>

The word >R places the item on the return stack and the word R> retrieves it from the return stack - an experienced Forth programmer would optimize this definition even further. Note that for technical reasons all words listed cannot be used outside definitions, so it may be argued that Forth doesn't have topic variables.

J

With this new definition of topic variables, the closest thing J has to a topic variable is probably dummy variables used in function definitions, because we always omit declaring which variables they are, and because we may omit them entirely. But, we still need to place the function in the context of the value it's being used on.

Thus, for example:

<lang J> example=: *:, %: NB. *: is square, %: is square root

  example 3

9 1.73205</lang>

Or course, if it's crucial to the concept of topic variables that they not be constrained to definitions of things like functions, then it might be argued that J does not have them.

On the third hand, note that "definitions of functions" do not actually need to be associated with names. At worst, some definitions might need to be enclosed in parenthesis:

<lang J> (*:, %:) 3 9 1.73205</lang>

And if we were to insist on leaving out functions, it's not clear that there would be much of anything left of the language to be doing anything with. See also Henry Rich's writeup on Tacit Programs.

PARI/GP

gp is a REPL for GP, within which % can be used to refer to the last result. <lang parigp>3 [sqrt(%),%^2]</lang>

Output:
%1 = 3
%2 = [1.7320508075688772935274463415058723670, 9]

Perl

In Perl the topic variable is $_. It is the default argument for many functions, including the square root. It is also the default parameter for loops:

<lang Perl>my $_ = 3; print for $_**2, "\n", sqrt;</lang>

The topic parameter is lexical, so its use can be nested into several lexical scopes. However, assignment to the topic variable at loop declaration is not lexical, and a my function or local keyword is needed to enable the loops to nest:

<lang perl>for ($_ = 0; $_ <= 9; $_++) {

 print "Outer";
 print "$_\n";
 # The inner loop will not nest properly unless
 # it is preceded by a my statement
 my $_;    # This is required to nest the inner loop
 for ($_ = 0; $_ <= 9; $_++) {
   print "Inner";
   print "$_\n";
 }
 # Alternatively we can use a local keyword in the
 # inner loop declaration instead of a my statement
 for (local $_ = 0; $_ <= 9; $_++) {
   print "Alternative";
   print "$_\n";
 }

}</lang>

Perl 6

As in previous versions of Perl, in Perl6 the topic variable is $_. In addition to a direct affectation, it can also be set with the 'given' keyword. A method can be called from it with an implicit call:

<lang Perl 6>given 3 {

   .say for $_**2, .sqrt;

}</lang> The scope of the $_ variable is always lexical in Perl 6, though a function can access its caller's topic if it asks for it specially via CALLER::<$_>.

PicoLisp

<lang PicoLisp>PicoLisp sets the value of the variable (symbol) '@' to the result of conditional and controlling expressions in flow- and logic-functions (cond, if, and, when, while, etc.).

Within a function or method '@' behaves like a local variable, i.e. its value is automatically saved upon function entry and restored at exit.

For example, to read the current input channel until EOF, and print the square of every item which is a number:</lang> Test: <lang PicoLisp>(while (read)

  (when (num? @)
     (println (* @ @)) ) )

abc # Not a number 7 # Number 49 # -> print square xyz # Not a number 3 # Number 9 # -> print square</lang>

Python

Pythons REPL has _. <lang python>>>> 3 3 >>> _*_, _**0.5 (9, 1.7320508075688772) >>> </lang>

Racket

Racket doesn't have a "built-in" concept of a topic variable, but one is easy to add to the language with some macros. In fact, the subject of adding such a facility to a language using a hygienic macro facility is a very popular topic in some macro circles, and Racket can do it very well using syntax parameters. In the following there is a demonstration of two implementation approaches, the first uses a "parameter" -- a runtime value that is bound to a value in some dynamic extent, and the second uses a "syntax parameter" which is something that refers indirectly to a plain binding, and this binding can be adjusted by macros to point at an existing "real" binding. See the end of the code for usage samples. (Note that there is no point to talk about how these things behave wrt scope: since Racket is flexible enough to implement these with very different scopes...)

<lang racket>

  1. lang racket

(module topic1 racket

 ;; define $ as a "parameter", but make it look like a plain identifier
 (provide $ (rename-out [$if if] [$#%app #%app]))
 (define current-value (make-parameter #f))
 (define-syntax $
   (syntax-id-rules (set!)
     [(_ x ...) ((current-value) x ...)]
     [(set! _ val) (current-value val)]
     [_ (current-value)]))
 ;; make an `if' form that binds it to the condition result
 (define-syntax-rule ($if C T E)
   (parameterize ([current-value C])
     (if $ T E)))
 ;; function application with []s uses the topic variable for the first arg
 (define-syntax ($#%app stx)
   (syntax-case stx ()
     [(_ f x y ...) (equal? #\[ (syntax-property stx 'paren-shape))
      #'(parameterize ([current-value x]) (f y ...))]
     [(_ f x ...) #'(f x ...)])))

(module topic2 racket

 ;; better variant: define `$' as a syntax parameter, which is adjusted to an
 ;; actual local binding; make it work in `if', and have a function definition
 ;; form that binds it to the actual arguments
 (provide $ (rename-out [$if if]) defun)
 (require racket/stxparam)
 (define-syntax-parameter $ (λ(stx) (raise-syntax-error '$ "not in scope")))
 (define-syntax-rule ($if C T E)
   (let ([c C]) (syntax-parameterize ([$ (make-rename-transformer #'c)])
                  (if c T E))))
 (define-syntax-rule (defun name body ...)
   (define (name arg)
     (syntax-parameterize ([$ (make-rename-transformer #'arg)])
       body ...)))
 )

(module sample1 racket

 (require (submod ".." topic1))
 (if (memq 2 '(1 2 3)) (cadr $) 'missing)
 ;; => 3
 (define (foo) (list (sqrt $) (* $ $)))
 [foo 9]
 ;; => '(3 81)
 )

(require 'sample1)

(module sample2 racket

 (require (submod ".." topic2))
 (if (memq 2 '(1 2 3)) (cadr $) 'missing)
 ;; => 3
 (defun foo (list (sqrt $) (* $ $)))
 (foo 9)
 ;; => '(3 81)
 )

(require 'sample2) </lang>

Ruby

In Ruby the topic variable is $_ (same as Perl).

<lang ruby>while DATA.gets # assigns to $_ (local scope)

 print             # If no arguments are given, prints $_

end __END__ This is line one This is line two This is line three</lang>

Output:
This is line one
This is line two
This is line three

example: <lang ruby>DATA.gets p [$_.to_i ** 2, Math.sqrt($_.to_i)] #=> [9, 1.7320508075688772] __END__ 3</lang> The style of programming using $_ as an implicit parameter is gradually losing favor in the Ruby community.

Standard ML

The SML language itself does not define a topic variable, but interactive implementations may define their own. For example the SML/NJ REPL defines a topic variable named it which is bound any time the user types an expression in the REPL (as opposed to a declaration).

<lang sml>- 3.0; val it = 3.0 : real - it * it; val it = 9.0 : real - Math.sqrt it; val it = 3.0 : real -</lang>

UNIX Shell

The shell $? is a kind of limited topic variable that holds the return value of the last function called. However, using it in a function will change its value, so following the echo below, the dollarhook will now contain the return value of zero indicating a successful echo:

<lang sh>multiply 3 4 # We assume this user defined function has been previously defined echo $? # This will output 12, but $? will now be zero indicating a successful echo</lang>