Introspection

From Rosetta Code
Revision as of 20:35, 13 September 2007 by rosettacode>Crc (→‎[[Toka]]: Added part 1 of the task)
Task
Introspection
You are encouraged to solve this task according to the task description, using any language you may know.

This task asks to

  • verify the version/revision of your currently running (compiler/interpreter/byte-compiler/runtime environment/whatever your language uses) and exit if it is too old.
  • check whether the variable "bloop" exists and whether the math-function "abs()" is available and if yes compute abs(bloop).

Befunge

Befunge has a different kind of introspection; the code space is also the data space of the program. Programs can be read and modified on the fly. For example, this Quine program works by reading and printing each character of the source. (This is a implicit loop, since the Befunge codespace wraps around.)

:0g,:66+`#@_1+

E

def version := interp.getProps()["e.version"]

(There is no built-in version comparison, and the author of this example assumes that implementing a version comparison algorithm isn't the point of this task.)

escape fail {
    def &x := meta.getState().fetch("&bloop", fn { fail("no bloop") })
    if (!x.__respondsTo("abs", 0)) { fail("no abs") }
    x.abs()
}

Forth

Standard Forth doesn't necessarily provide for version numbers, but you can query information about the environment at interpretation time:

s" MAX-U" environment? [IF]
   0xffffffff <> [IF] .( Requires 32 bits! ) bye [THEN]
[THEN]
[defined] bloop [if]
[defined] abs [if]
  bloop abs
[then] [then]

Perl

Interpreter: Perl 5.x

require v5.6.1;    # run time version check
require 5.6.1;     # ditto
require 5.006_001; # ditto; preferred for backwards compatibility

Checking whether a variable exists is kind of daft. Good style dictates that I declare the variables I'm going to use, and then I already know $bloop exists. Checking for the value of a variable however is something very common.

defined $bloop;
# returns true if bloop has been filled with something useful

What if 'bloop' is a computed value? Good style forbids that I dereference willy-nilly variables with unknown names, that's what hashes are good for.

$computed = 'bloop';
exists $introspect{$computed};
# returns true if the key bloop exists in hash %introspect

In Perl, you cannot check for the existance of built-in functions, of which abs() is one. However in practice that's not a problem because most functions live in classes, and those are easily inspectable at runtime.

use UNIVERSAL qw(can);
use Math::Cephes qw();
print Math::Cephes->fabs($bloop) if can 'Math::Cephes', 'fabs';

Pop11

Variable pop_internal_version contains Poplog version in numeric form (as an integer) -- this one is most convenient for version checks. For printing one can use pop_version (which is a string containing more information).

;;; Exit if version below 15.00
if pop_internal_version < 150000 then
    sysexit()
endif;

Pop11 variables are named by words. Pop11 word is a unique version of string stored in dictionary. So we need first convert strings to words and then query about words. Pop11 variables can store any value including functions and in fact when one accesses a function like abs by name one merely access a variable abs which happen to hold predefined function abs. To follow spirit of the task as closely as possible we check if abs indeed holds functional value.

;;; We do main task in a procedure
define check_and_call(x, y);
   lvars wx=consword(x), wy=consword(y);
   if identprops(wx) = 0 and isprocedure(valof(wx))
      and identprops(wy) = 0 then
          return(valof(wx)(valof(wy)));
   else
        return("failed");
   endif;
enddefine;
;;; Prints failed because bloop is undefined
check_and_call('abs' , 'bloop') =>
;;; Define bloop
vars bloop = -5;
;;; Now prints 5
check_and_call('abs' , 'bloop') =>

Note that here bloop is defined as "permanent" variable, Pop11 also have lexical variables which are not available for introspection.

Ruby

 exit if RUBY_VERSION < '1.8.6'
 puts bloop.abs if defined?(bloop) and bloop.respond_to?(:abs)


Tcl

package require Tcl 8.2 ; # throws an error if older
if {[info exists bloop] && [llength [info functions abs]]} {
  puts [expr abs($bloop)]
}


Toka

Starting with Release 1.1, Toka allows for checking the version number:

VERSION 101 > [ bye ] ifFalse

Release 1.0 can be detected by doing:

` VERSION FALSE = [ bye ] ifTrue

Basic introspection is possible via `

` bloop FALSE <> ` abs FALSE <> and [ ` bloop invoke @ ` abs invoke ] ifTrue