Introspection: Difference between revisions

(add RPL)
 
(5 intermediate revisions by 5 users not shown)
Line 709:
{{out}}
<pre>bloop does not exist</pre>
 
=={{header|Frink}}==
<syntaxhighlight lang="frink">if FrinkVersion[] < "2024-01-01"
{
println["Version of Frink is too old."]
exit[]
}
 
if isVariableDefined["bloop"]
{
func = getFunction["abs",1]
if func != undef
println[func[bloop]]
}</syntaxhighlight>
 
=={{header|GAP}}==
Line 946 ⟶ 960:
 
=={{header|jq}}==
jq's powers of introspection are currently very limited, being
essentially confined to the built-in function `builtins`, which
as the name suggests only yields information about built-in filters (name and arity).
 
'''Works with jq, the C implementation of jq'''
Version information can however be made available to a running jq program as illustrated here:
 
'''Works with gojq, the Go implementation of jq'''
jq --arg version $(jq --version) '$version'
 
jq's support for introspection is limited. For example, jq's version
References to undefined functions and undefined variables (that is jq's "$-variables")
number is available from the command-line but not as a built-in; and
are regarded as errors that cannot be caught, but in a pinch one can use the
it is not in general possible to check whether a variable has been
technique illustrated here:
defined without causing an error. However, jq does make it possible
for a program to check whether a variable has been defined globally,
so we'll go with that.
 
Note that jq's `builtins` function provides details about jq's built-in
jq -n --argjson bloop null 'if $bloop then $bloop|length else "undefined" end'
functions, and similarly the `modulemeta` function provides some support for
introspection within modules, but otherwise there is no support for
determining the functions that have been user-defined.
 
Assuming JQ has been defined appropriately as a shell variable, one could
As it happens, jq's "abs" function is named "length" (don't ask why),
invoke jq with a global "bloop" variable as follows:
so the task regarding `abs()` cannot really be accomplished using the name `abs`.
<pre>
$JQ -n --arg version "$($JQ --version)" --argjson bloop -3 -f introspection.jq
</pre>
 
The following program has been tested with recent versions of both jq
and gojq, but may fail with earlier versions. Note also that
jq's `length` has the semantics of `abs` when applied to numbers,
so if your jq does not support `abs` by that name, you could use `length`.
 
<syntaxhighlight lang="jq">
def checkVersion:
$version
| capture("^[^- ]*(?<jq>[- ])(?<major>[0-9]*)[.](?<minor>[0-9]*)") // {jq: 0}
| if .jq == 0 then "unrecognized version identification: \($version)" | error
elif .jq == "-" # jq
and (.major < "1" or (.major == "1" and .minor < "5"))
then "version \($version) is too old" | error
elif .jq == " " # gojq
and (.major == "0" and (.minor | tonumber) < 12)
then "version \($version) is too old" | error
else .
end;
 
checkVersion
# Check that abs/0 is defined
| (builtins | index("abs/0")) as $ix
| if $ix == null then "abs/0 not available" | error else . end
 
# Is bloop a global variable?
| if ($ARGS.named | has("bloop")) then $ARGS.named["bloop"] | abs
else "There is no globally defined variable name $bloop." | error
end
</syntaxhighlight>
Examples:
{{output}}
<pre>
$ gojq -n --arg version "$(gojq --version)" --argjson bloop -3 -f introspection.jq
3
 
$ jq -n --arg version "$(jq --version)" -f introspection.jq
jq: error (at <unknown>): There is no globally defined variable name bloop.
</pre>
 
=={{header|Jsish}}==
Line 2,194 ⟶ 2,254:
Note: The warning is because it accessed the global variable which was made invalid.<br>
The meaning of these variables can be found many places, including [http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Variables_and_Constants here].
 
=={{header|Rust}}==
 
Checking for the Rust compiler version can be done using external crates, for example using the rustc_version crate. Simply add the rustc_version dependency into your cargo.toml file under the dependencies:
 
<syntaxhighlight lang="toml">
[dependencies]
rustc_version = "0.4"
</syntaxhighlight>
 
Then we can write code that can check the rust compiler channel, the rust compiler version and check for a minimum version of the rust compiler:
 
<syntaxhighlight lang="rust">
use rustc_version::{version_meta, Channel, version, Version};
 
fn main() {
// We can check the Rust channel currently being used: stable, nightly, etc.
match version_meta().unwrap().channel {
Channel::Stable => {
println!("Rust Stable");
}
Channel::Beta => {
println!("Rust Beta");
}
Channel::Nightly => {
println!("Rust Nightly");
}
Channel::Dev => {
println!("Rust Dev");
}
}
// We can print the Rust compiler version
println!("{}",version().unwrap());
// We can check for a minimum Rust compiler version
if version().unwrap() >= Version::parse("1.50.0").unwrap() {
println!("Rust compiler version is ok.");
} else {
eprintln!("Rust compiler version is too old. Please update to a more recent version.");
std::process::exit(1);
}
}
</syntaxhighlight>
 
When running the code using the stable Rust compiler version 1.71.1 it results in:
 
<pre>
Rust Stable
1.74.1
Rust compiler version is ok.
</pre>
 
There are currently no runtime capabilities built into the Rust compiler for checking whether individual variables or individual functions have been declared. Some crates offer specialized, limited and experimental reflection capabilities; for example for introspecting struct fields we can use the crates introspection or bevy_reflect. Macros and build scripts can also be leveraged as a current workaround for specific and limited scenarios.
 
=={{header|Scala}}==
Line 2,425 ⟶ 2,539:
Note that:
 
* ''Process.version'' is not available in the release version of Wren CLI v0.3.0 but is available in the latest build (recommended for RC use).
* Wren doesn't have reflection as such but is able to obtain and analyze the running script's source code. It is assumed for this purpose that the latter is sensibly formatted - only global declarations are not indented.
* Wren is dynamically typed and has a Num type but not an integer type. As far as the extra credit is concerned, the simplifying assumption has been made that a global variable is an integer if it's assigned an integer literal when it's declared.
<syntaxhighlight lang="ecmascriptwren">import "os" for Platform, Process
import "io" for File
import "meta" for Meta
import "./pattern" for Pattern
import "./math" for Nums
 
var a = 4 /* 1st integer variable */
Line 2,443 ⟶ 2,556:
var version = Process.version
var components = version.split(".")
if (Num.fromString(components[1]) < 34) {
Fiber.abort("Wren version (%(version)) is too old.")
}
Line 2,473 ⟶ 2,586:
var vars = res[0]
var vals = res[1]
System.print("The sum of the %(vars.count) integer variables, %(vars), is %(Nums.sum(vals))")</syntaxhighlight>
 
{{out}}
Line 2,483 ⟶ 2,596:
=={{header|Yabasic}}==
<syntaxhighlight lang="yabasic">if peek("version") < 2.63 error "Interpreter version is too old!"</syntaxhighlight>
 
=={{header|Zig}}==
 
'''Works with:''' 0.10.1, 0.11.0, 0.12.0-dev.1577+9ad03b628
 
Note that errors for compiler version check and @hasDecl/@hasField are usually reported at comptime via @compileError, not at runtime, but for demonstrating purposes output is moved to runtime (introspection is still at comptime).
 
<syntaxhighlight lang="zig">const std = @import("std");
const builtin = @import("builtin");
 
pub const bloop: i32 = -1_000;
 
pub fn abs(a: i32) i32 {
return if (a < 0) -a else a;
}
 
pub fn main() error{NotSupported}!void {
if (builtin.zig_version.order(.{ .major = 0, .minor = 11, .patch = 0 }) == .lt) {
std.debug.print("Version {any} is less than 0.11.0, not suitable, exiting!\n", .{builtin.zig_version});
return error.NotSupported;
} else {
std.debug.print("Version {any} is more or equal than 0.11.0, suitable, continuing!\n", .{builtin.zig_version});
}
 
if (@hasDecl(@This(), "bloop") and @hasDecl(@This(), "abs")) {
std.debug.print("abs(bloop) = {d}\n", .{abs(bloop)});
} else {
std.debug.print("abs and/or bloop are not defined!\n", .{});
}
}</syntaxhighlight>
 
{{out|case=Zig version 0.10.1}}
<pre>
Version 0.10.1 is less than 0.11.0, not suitable, exiting!
error: NotSupported
src/instrospection.zig:13:9: 0x211a1e in main (instrospection)
return error.NotSupported;
^
</pre>
 
{{out|case=Zig version 0.11.0}}
<pre>
Version 0.11.0 is more or equal than 0.11.0, suitable, continuing!
abs(bloop) = 1000
</pre>
 
{{out|case=Zig version 0.12.0-dev.1577+9ad03b628}}
<pre>
Version 0.12.0-dev.1577+9ad03b628 is more or equal than 0.11.0, suitable, continuing!
abs(bloop) = 1000
</pre>
 
===Extra credit===
 
<syntaxhighlight lang="zig">const std = @import("std");
 
pub const first_integer_constant: i32 = 5;
pub const second_integer_constant: i32 = 3;
pub const third_integer_constant: i32 = -2;
 
pub const some_non_integer_constant: f32 = 0.0;
pub const another_non_integer_constant: bool = false;
 
pub fn main() void {
comptime var cnt: comptime_int = 0;
comptime var sum: comptime_int = 0;
inline for (@typeInfo(@This()).Struct.decls) |decl_info| {
const decl = @field(@This(), decl_info.name);
switch (@typeInfo(@TypeOf(decl))) {
.Int, .ComptimeInt => {
sum += decl;
cnt += 1;
},
else => continue,
}
}
 
@compileLog(std.fmt.comptimePrint("cnt = {d}, sum = {d}", .{ cnt, sum }));
}</syntaxhighlight>
 
{{out}}
<pre>
src/instrospection.zig:24:5: error: found compile log statement
@compileLog(std.fmt.comptimePrint("cnt = {d}, sum = {d}", .{ cnt, sum }));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
Compile Log Output:
@as(*const [16:0]u8, "cnt = 3, sum = 6")
</pre>
 
=={{header|zkl}}==
2,507

edits