Can I create an operator in Tcl? - operators

I want to create a new operator in Tcl, by operator I mean a proc that could be used in the following way:
$a**2 instead of pow($a,2)
Or in my case I want an operator that does the same as <= and >= but for floating point numbers, meaning:
proc <f= {a b {epsilon 1e-15} {
if {$a < $b} {return 1}
return [expr abs($a - $b) < $epsilon]
}
But I want to use it as:
if {$a <f= $b} {...
instead of"
if {[<f= $a $b]} {...
and the same for >f=

You can't implement exactly this, but there is one option which might help.
Since Tcl 8.5, it's possible to define arbitrary functions for expr mini-language by creating commands in the tcl::mathfunc namespace, observe:
% set tcl::mathfunc::epsilon 1e-15
1e-15
% proc tcl::mathfunc::feq {a b} {
variable epsilon
expr {abs($a - $b) < $epsilon}
}
% expr { feq(1, 2) }
0
% expr { feq(1, 1) }
1
% expr { feq(1, 1 + 1e-16) }
1
% if {feq(1, 1 + 1e-16)} { puts OK } else { puts FAIL }
OK
And with a bit of import/export mumbo-jumbo you can happily make this function be available as a command in your root namespace:
% namespace eval tcl::mathfunc { namespace export feq }
% namespace import tcl::mathfunc::feq
% feq 1 1
1
% feq 1 [expr {1 + 1e-10}]
0
% feq 1 [expr {1 + 1e-16}]
1
(Alternatively, you could create your command in any convenient namespace and then import it into the tcl::mathfunc namespace.)
Not exactly what you want, but comes close enough in my opinion.
Note also that since 8.5 Tcl has a special namespace tcl::mathop which exposes all expr operators as commands, but you can't really modify this namespace in any way (but can use commands from it).

TCL itself is strictly prefix notation so the superficial answer is no you can't ...
however you can also do some radical things with unknown or you could implement your own version of something like expr which can parse its arguments anyway it likes

Related

how to make a context aware code evaluator

I was looking at REPL-like evaluation of code from here and here, and tried to make a very small version for it, yet it fails:
use nqp;
class E {
has Mu $.compiler;
has $!save_ctx;
method evaluate(#fragments) {
for #fragments -> $code {
my $*MAIN_CTX;
my $*CTXSAVE := self;
$!compiler.eval($code,
outer_ctx => nqp::ctxcaller(nqp::ctx()));
if nqp::defined($*MAIN_CTX) {
$!save_ctx := $*MAIN_CTX;
}
}
}
method ctxsave(--> Nil) {
say "*in ctxsave*";
$*MAIN_CTX := nqp::ctxcaller(nqp::ctx());
$*CTXSAVE := 0;
}
}
my $e := E.new(compiler => nqp::getcomp("Raku"));
nqp::bindattr($e, E, '$!save_ctx', nqp::ctx());
$e.evaluate: ('say my #vals = 12, 3, 4;', 'say #vals.head');
I pieced together this from the above links without very much knowing what I'm doing :) When run, this happens:
*in ctxsave*
[12 3 4]
===SORRY!=== Error while compiling file.raku
Variable '#vals' is not declared. Did you mean '&val'?
file.raku:1
------> say ⏏#vals.head
with Rakudo v2022.04. First fragment was supposed to declare it (and prints it). Is it possible to do something like this, so it recognizes #vals as declared?
You can do it in pure Raku code, although depending on the not-exactly-official context parameter to EVAL.
# Let us use EVAL with user input
use MONKEY;
loop {
# The context starts out with a fresh environment
state $*REPL-CONTEXT = UNIT::;
# Get the next line of code to run.
my $next-code = prompt '> ';
# Evaluate it; note that exceptions with line numbers will be
# off by one, so may need fixups.
EVAL "\q'$*REPL-CONTEXT = ::;'\n$next-code", context => $*REPL-CONTEXT;
}
Trying it out:
$ raku simple-repl.raku
> my $x = 35;
> say $x;
35
> my $y = 7;
> say $x + $y;
42

IIFE alternatives in Raku

In Ruby I can group together some lines of code like so with a begin block:
x = begin
puts "Hi!"
a = 2
b = 3
a + b
end
puts x # 5
it's immediately evaluated and its value is the last value of the block (a + b here) (Javascripters do a similar thing with IIFEs)
What are the ways to do this in Raku? Is there anything smoother than:
my $x = ({
say "Hi!";
my $a = 2;
my $b = 3;
$a + $b;
})();
say $x; # 5
Insert a do in front of the block. This tells Raku to:
Immediately do whatever follows the do on its right hand side;
Return the value to the do's left hand side:
my $x = do {
put "Hi!";
my $a = 2;
my $b = 3;
$a + $b;
}
That said, one rarely needs to use do.
Instead, there are many other IIFE forms in Raku that just work naturally without fuss. I'll mention just two because they're used extensively in Raku code:
with whatever { .foo } else { .bar }
You might think I'm being silly, but those are two IIFEs. They form lexical scopes, have parameter lists, bind from arguments, the works. Loads of Raku constructs work like that.
In the above case where I haven't written an explicit parameter list, this isn't obvious. The fact that .foo is called on whatever if whatever is defined, and .bar is called on it if it isn't, is both implicit and due to the particular IIFE calling behavior of with.
See also if, while, given, and many, many more.
What's going on becomes more obvious if you introduce an explicit parameter list with ->:
for whatever -> $a, $b { say $a + $b }
That iterates whatever, binding two consecutive elements from it to $a and $b, until whatever is empty. If it has an odd number of elements, one might write:
for whatever -> $a, $b? { say $a + $b }
And so on.
Bottom line: a huge number of occurrences of {...} in Raku are IIFEs, even if they don't look like it. But if they're immediately after an =, Raku defaults to assuming you want to assign the lambda rather than immediately executing it, so you need to insert a do in that particular case.
Welcome to Raku!
my $x = BEGIN {
say "Hi!";
my $a = 2;
my $b = 3;
$a + $b;
}
I guess the common ancestry of Raku and Ruby shows :-)
Also note that to create a constant, you can also use constant:
my constant $x = do {
say "Hi!";
my $a = 2;
my $b = 3;
$a + $b;
}
If you can have a single statement, you can leave off the braces:
my $x = BEGIN 2 + 3;
or:
my constant $x = 2 + 3;
Regarding blocks: if they are in sink context (similar to "void" context in some languages), then they will execute just like that:
{
say "Executing block";
}
No need to explicitely call it: it will be called for you :-)

Rational numbers in Raku

I am using Raku for some computations, because it has nice numeric types. However, I have an issue with using '.raku'
say (1/6+1/6).raku
#<1/3>
We obtain this. However,
say (1/10+1/10).raku
#0.2
Is it a bug? I expected <1/5>. What happens?
In Raku, 0.2 constructs a Rat, and thus produces the very same result as writing 1/5 (which will be constant folded) or <1/5> (the literal form). You only get floating point in the case of specifying an exponent (for example, 2e-1).
The .raku (formerly known as the .perl) method's job is to produce something that will roundtrip and produce the same value if EVAL'd. In the case of 1/5, that can be exactly represented as a decimal, so it will produce 0.2. It only resorts to the fractional representation when a decimal form would not round-trip.
You can always recover the numerator and denominator using the .numerator and .denominator methods to format as you wish. Additionally .nude method returns a list of the numerator and denominator, which one can join with a / if wanted:
say (1/6+1/6).nude.join("/"); # 1/3
say (1/10+1/10).nude.join("/"); # 1/5
Hi #milou123 I was also a bit surprised that raku reverts to decimal representation - I can see that some contexts - such as teaching fractional arithmetic would benefit from having a "keep as rat" mode. Having said that, ultimately it makes sense that there is only one way to .raku something and that decimal is the default representation.
Of course, with raku, you can also just change the language a bit. In this case, I have invented a new '→' postfix operator...
multi postfix:<→> ( Rat:D $r ) { $r.nude.join("/") }
say (1/5+1/5)→; # 2/5
I am not smart enough to work out if the built in 'raku' method can be overridden in a similar way, would be keen to see advice on how to do that concisely...
try this in Julia:
julia> 1 // 10 + 1 // 10
1//5
julia> typeof(1 // 10 + 1 // 10)
Rational{Int64}
julia> 1 // 2 + 1 // 3
5//6
julia> typeof(1 // 2 + 1 // 3)
Rational{Int64}
in the Rat.pm6 implemention, we can only call .raku method on Rat type to get the expected format:
multi method raku(Rat:D: --> Str:D) {
if $!denominator == 1 {
$!numerator ~ '.0'
}
else {
my $d = $!denominator;
unless $d == 0 {
$d = $d div 5 while $d %% 5;
$d = $d div 2 while $d %% 2;
}
if $d == 1 and (my $b := self.base(10,*)).Numeric === self {
$b;
}
else {
'<' ~ $!numerator ~ '/' ~ $!denominator ~ '>'
}
}
}

TCL multiple assignment (as in Perl or Ruby)

In Ruby or Perl one can assign more than variable by using parentheses. For example (in Ruby):
(i,j) = [1,2]
(k,m) = foo() #foo returns a two element array
Can one accomplish the same in TCL, in elegant way? I mean I know that you can
do:
foreach varname { i j } val { 1 2 } { set $varname $val }
foreach varname { k m } val [ foo ] { set $varname $val }
But I was hoping for something shorter/ with less braces.
Since Tcl 8.5, you can do
lassign {1 2} i j
lassign [foo] k m
Note the somewhat unintuitive left-to-right order of value sources -> variables. It's not a unique design choice: e.g. scan and regexp use the same convention. I'm one of those who find it a little less readable, but once one has gotten used to it it's not really a problem.
If one really needs a Ruby-like syntax, it can easily be arranged:
proc mset {vars vals} {
uplevel 1 [list lassign $vals {*}$vars]
}
mset {i j} {1 2}
mset {k m} [foo]
Before Tcl 8.5 you can use
foreach { i j } { 1 2 } break
foreach { k m } [ foo ] break
which at least has fewer braces than in your example.
Documentation: break, foreach, lassign, list, proc, uplevel

Lex Yacc / Flex Bison variables

I was just wondering how any of you guys would implement multi character variables in c using Flex and Bison / Lex and Yacc ?
Any if so can you provide maybe a simple example?
I am attempting to write an interpreter for a language and I can't seem to find a good way to implement variables, so far the methods I've tried have either failed or causing the execution of any program with a lot of variables become really so (I mean it could take minutes to execute a program that just assigns 1000 variables and does nothing else)
Thanks for your time,
Francis
In a lexer provided by ADAIC for Ada the following method is used, i find it ver useful for lexing multu-character literals such as reserved words and variables. It (along with corresponding Bison grammar and some other stuff) is available at ADAIC docs
%%
[a-zA-Z](_?[a-zA-Z0-9])* return(lk_keyword(yytext));
%%
# define NUM_KEYWORDS 69
KEY_TABLE key_tab[NUM_KEYWORDS] =
{
{"ABORT", ABORT},
{"ABS", ABS},
....
....
....
};
lk_keyword(str)
char *str;
{
int min;
int max;
int guess, compare;
min = 0;
max = NUM_KEYWORDS-1;
guess = (min + max) / 2;
to_upper(str);
for (guess=(min+max)/2; min<=max; guess=(min+max)/2) {
if ((compare = strcmp(key_tab[guess].kw, str)) < 0) {
min = guess + 1;
} else if (compare > 0) {
max = guess - 1;
} else {
return key_tab[guess].kwv;
}
}
return identifier;
}