Variable substitution in tcl - object

I'm running an incarnation of tcl 8.5 that has been embedded into another system.
That system will accept and correctly execute a command such as:
uniformDist minAndMax {1 10}
where uniformDist is some object to which I do not have internal visibility.
I want to be able to say something like:
set M 1000
uniformDist minAndMax {1 M}
but this does not work.
Nor does
set M 1000
uniformDist minAndMax {1 $M}
I tried:
u minAndMax {1 [eval $M]}
and
u minAndMax {1 [eval M]}
Neither of those works.
The error message is:
expected a real value: unable to convert from: "$M"Error: expected
fewer arguments [Error while parsing pair]
or
expected a real value: unable to convert from: "[eval"Error: expected
fewer arguments [Error while parsing pair]
What is the right way that tcl does this?

Variable substitution is expressed using $ and the variable's name (such as $M or ${M}).
This doesn't work:
uniformDist minAndMax {1 $M}
because the braces prevent substitution: $M is just the (sub)string 'dollar, upper case m'.
This works:
uniformDist minAndMax [list 1 $M]
because the arguments to list will be evaluated before the list {1 1000} is returned and passed to uniformDist.
The form "1 $M" would work too, and the command substitution [set M] can be used instead of the variable substitution above.
Documentation:
Summary of Tcl language syntax

Related

Creating y shape random float array in J

I am trying to creating y shape random float array, and this is my current right now:
input_dim =: 2
hidden_dim =: 16
0 ?#$ ~ (input_dim, hidden_dim)
0.838135 0.96131 0.766721 0.420625 0.640265 0.683779 0.683311 0.427981 0.281479 0.305607 0.385446 0.898389 0.24596 0.452391 0.739534 0.973384
0.914155 0.172582 0.146184 0.624908 0.333564 0.132774 0.475515 0.802788 0.277571 0.146896 0.40596 0.735201 0.943969 0.259493 0.442858 0.374871
It seems like this code returns what I exactly want, so I tried to make a function like below:
rand =: 0 ?#$ ~
but rand (input_dim, hidden_dim) gives me a syntax error...
I think I am missing one very important part, but I am not sure what that is.
Any advice would be grateful!
The only thing missing from your verb is ].
That is:
rand =: 0 ?#$~ ]
rand 2 3
0.891663 0.888594 0.716629
0.9962 0.477721 0.946355
Potentially your confusion arose because you were wanting to create a fork of the form (noun verb verb), however ~ is an adverb and so combines with the verb to its left to create a new verb (in your case ?#$~) so your rand had the form (0 ?#$~) or (noun verb) which J does not recognise - hence the syntax error.
It makes sense to use the combination ?#$ if possible because it is supported by special code and does not create x $ y.
Without the argument, the syntax of 0 ?#$ ~ is ambiguous and the interpreter missclassifies the parenthesization (or, more accurately, the correct parenthesization is not the one you think it is).
The easiest way around this is to define rand as:
rand =: 3 :'0 ?#$ ~ y'
Of course, any other way of removing the syntactic ambiguity will also work:
rand =: [: ? 0 $~ ]
rand =: ?#(0$~])
rand =: ?#(0&($~))
...

How to have tcl switch return a constant value?

How do I get a switch to return a constant value? For example:
set z [switch a {
default {expr {{val}}}
}]
This contrived example sets z to val. Is expr the right way to return a constant string from a switch? It's a lot of braces. Is there a better way?
For constant expressions, it's not at all bad to use expr like that. Otherwise, if you're using Tcl 8.6 then you have string cat which will work perfectly for this when used with a single argument.
set z [switch a {
default {string cat "val"}
}]
Prior to 8.6 (or with very early point releases of 8.6) you needed to use this instead:
set z [switch a {
default {return -level 0 "val"}
}]
That actually works in the right way — it's bytecode-compiled efficiently too — but it has always felt very contrived to me.
I tend to put my sets inside my switches instead of the other way round, so this specific problem is usually moot for me. However, the techniques described here are extremely useful for the body of an lmap call.
A more common approach to return a value is to use the set command:
set z [switch a {
default {set _z val}
}]

How to include a expression in the name of file in Maxima

I have a Maxima program that does some algebra and then writes some things down on an external file. How do I include some calculated values and even small expressions into the name of the file?
A mwe would be the following:
N:3;
f: erf(x);
tay: taylor(f,x,0,N);
with_stdout("taylor.txt", fortran(tay));
But this example names the file taylor.txt. I wanted something that named the file taylor_N3_f_erf.txt or something like that. I have tried several syntaxes but nothing worked.
Also, I know Maxima in programmed in lisp and I learned the syntax for concatenating strings in Lisp but I haven't figured out how to use that in Maxima.
Thank you very much.
Here's what I came up with. It took some playing around with argument quoting and evaluation in functions but I think it works now.
(%i2) bar (name_base, name_extension, ['vars]) := sconcat (name_base, foo(vars), ".", name_extension) $
(%i3) foo(l) := apply (sconcat, join (makelist ("_", 2 * length (l)), join (l, map (string, map (ev, l))))) $
(%i4) [a, b, c] : [123, '(x + 1), '(y/2)];
y
(%o4) [123, x + 1, -]
2
(%i5) bar ("foobar", "txt", a, b, c);
(%o5) foobar_a_123_b_x+1_c_y/2.txt
(%i6) myname : bar ("baz", "quux", a, b);
(%o6) baz_a_123_b_x+1.quux
(%i7) with_stdout (myname, print ("HELLO WORLD"));
(%o7) HELLO WORLD
(%i8) printfile ("baz_a_123_b_x+1.quux");
HELLO WORLD
(%o8) baz_a_123_b_x+1.quux
Note that sconcat concatenates strings and string produces a string representation of an expression.
Division expressions could cause trouble since / means a directory in a file name ... maybe you'll have to subsitute for those characters or any other non-allowed characters. See ssubst.
Note that with_stdout evaluates its first argument, so if you have a variable e.g. myname then the value of myname is the name of the output file.

Detecting if a variable can be printed in Lua

I've got a variable that could be a number of types - sometimes it's a string, sometimes a number, table or bool. I'm trying to print out the value of the variable each time like this:
print("v: "..v)
with v being my variable. Problem is, when I get a value that can't be concatenated I get this error:
myscript.lua:79: attempt to concatenate a table value
I've tried changing it to this in case it manages to detect whether or not the variable can be printed:
print("v: "..(v or "<can't be printed>"))
but I had the same problem there. Is there some sort of function I can use to determine if a variable can be concatenated to a string, or a better way of printing out variables?
You can provide the values as separate arguments to print:
print("v:", v)
This would print something like
v: table: 006CE900
Not necessarily the most useful, but better than a crash if it's just for debugging purposes.
See here for information on more useful table printing.
tostring(v) works for all possible v values (including nil). So writing your line as:
print( "v: " .. tostring( v ) )
will always work.
Alternatively you could have a look at type( v ) and if its "string" print it, otherwise print something else (if that's what you want).

Wrapping J's Adverse primitive (::)

Usually, I will use the :: primitive thus:
SomeVariable"_ :: ] DefaultValue
I'm looking for a way to wrap that ugly SOB. I'm trying to reason it. Normally, it would be with a tacit definition. This, for example:
default =: 13 : 'x"_ :: ] y'
fails miserably. Because, of course, in this context:
SomeVariable default DefaultValue
if SomeVariable doesn't exist, J will throw a valence error.
So, how can you wrap ::?
You can indeed wrap :: but if you want to give it a verb argument, you need to deal with the syntactic issues.
For example, you can use an adverb:
fault=:1 :0
u"_ :: ]
)
Or you could convert the verb you are manipulating into a gerund and pass that in (but that would be ugly, so I do not think you want that).
I use,
ORdef_z_ =: ".#[^:(_1< 4!:0#<#[)
'asd' ORdef 3 NB. asd not assigned, returns right.
3
asd =. 'asd' ORdef 3
asd=.'asd' ORdef 22 NB. will return 3 due to previous assignment
asd
3

Resources