Temporary variable in AMPL - ampl

Is there a way in AMPL to declare and use temporary variables? What I mean by that is the "regular" variables used in programming (instead of model variables), especially in the .run file, such as saving a string for repeated use in the .run file:
some_file = sprintf(foo%u.txt, 3); # Temporary variable
print "Hello World" > some_file;
print "Hello again" > some_file;

If it's not variable within the optimisation that you're going to solve, then it's a parameter. You can change the parameter value with let, like so:
reset;
param blah symbolic;
let blah := "hello world";
print blah;
let blah := "this parameter has changed";
print blah;
Parameters in AMPL are number by default; string params need to be explicitly declared as symbolic.
Note that I've declared the param in a separate statement from the first assignment. If I were to assign a value in the declaration, like param blah symbolic := "hello world";, then it would fail when I try to change the value.

Related

Using a default value for a function parameter which depends of other parameter

I'd like to create an script which takes an input file and optionally an output file. When you don't pass an output file, the script uses the same filename as the input but with the extension changed. I don't know how to write a default parameter which changes the extension.
#!/usr/bin/env raku
unit sub MAIN(
Str $input where *.IO.f, #= input file
Str $output = $input.IO.extension("txt"), #= output file
Bool :$copy, #= copy file
Bool :$move, #= move file
);
Unfortunately that doesn't work:
No such method 'IO' for invocant of type 'VMNull'
in block <unit> at ./copy.raku line 5
How can I do something like that?
error message is less than awesome but program not working is expected because you have in the signature
Str $output = $input.IO.extension("txt")
but the right hand side returns an IO::Path object with that extension but $output is typed to be a String. That is an error:
>>> my Str $s := "file.csv".IO.extension("txt")
Type check failed in binding; expected Str but got IO::Path (IO::Path.new("file.t...)
in block <unit> at <unknown file> line 1
>>> sub fun(Str $inp, Str $out = $inp.IO.extension("txt")) { }
&fun
>>> fun "file.csv"
Type check failed in binding to parameter '$out'; expected Str but got IO::Path (IO::Path.new("file.t...)
in sub fun at <unknown file> line 1
in block <unit> at <unknown file> line 1
Sometimes compiler detects incompatible default values:
>>> sub yes(Str $s = 3) { }
===SORRY!=== Error while compiling:
Default value '3' will never bind to a parameter of type Str
------> sub yes(Str $s = 3⏏) { }
expecting any of:
constraint
but what you have is far from a literal, so runtime detection.
To fix it, you can either
change to Str() $output = $inp.IO.extension("txt") where Str() means "accept Any object and then cast it to Str". So $output will end up being a string like "file.txt" available in MAIN.
similar alternative: Str $output = $inp.IO.extension("txt").Str but it's repetitive in Str.
change to IO::Path() $output = $inp.IO.extension("txt"). Similarly, this casts to whatever recieved to an IO::Path object, so, e.g., you'll have "file.txt".IO available in $output. If you do this, you might want to do the same for $input as well for consistency. Since IO::Path objects are idempotent to .IO (in eqv sense), no other part of the code needs changing.

Unbind or undefine a variable in raku

After reading the Raku documentation, I only found this for undefining a variable. I believe that in Raku there are differences between assignment and binding.
Defining and undefining a scalar is easy.
> my $n
(Any)
> $n.defined
False
> $n = 3
3
> $n.defined
True
> $n = Nil
(Any)
> $n.defined
False
When the variable is binded, it's not possible.
> my $k := 5
5
> $k := Nil
===SORRY!=== Error while compiling:
Cannot use bind operator with this left-hand side
at line 2
------> <BOL>⏏<EOL>
> $k = Nil
Cannot assign to an immutable value
in block <unit> at <unknown file> line 1
For arrays or hashes, I can empty it, but the variable is still defined.
For functions, when you define a function with sub, you cannot undefine it, but you can with an anonymous function.
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> sub foo ($n) { $n + 1}
&foo
> &foo.defined
True
> &foo = Nil
Cannot modify an immutable Sub (&foo)
in block <unit> at <unknown file> line 1
So what's the difference between assignment and binding?
How can I undefine a variable?
Lots of different issues to discuss here.
> my $k := 5;
> $k := Nil;
Cannot use bind operator
This first problem is the Raku REPL. cf your last SO. Have you tried CommaIDE or repl.it?
Your code is perfectly valid:
my $k := 5;
$k := Nil;
say $k; # Nil
Moving on:
my $k := 5;
$k = Nil;
Cannot assign to an immutable value
This is different. After binding 5 to $k, the $k = Nil code is attempting to assign a value into a number. Only containers[1] support assignment. A number isn't a container, so you can't assign into it.
Clarifying some cases you mentioned but didn't explicitly cover:
my #foo;
#foo := Nil;
Type check failed in binding; expected Positional...
While scalar variables (ones with a $ sigil) will bind to any value or container, an # sigil'd variable will only bind to a Positional container such as an Array. (Likewise a % to an Associative such as a Hash.)
Not only that, but these containers are always defined. So they still return True for .defined even if they're empty:
my #foo := Array.new; # An empty array
say #foo.elems; # 0 -- zero elements
say #foo.defined; # True -- despite array being empty
Now assigning Nil to an array:
my #foo;
#foo = Nil;
say #foo; # [(Any)]
If a declaration of an # sigil'd variable doesn't bind it to some explicit Positional type it is instead bound to the default choice for an # variable. Which is an Array with a default element value of Any.
The #foo = Nil; statement above assigns a Nil value into the first element of #foo. The assignment of a value into a non-existing element of a multi-element container means a new Scalar container pops into existence and is bound to that missing element before assignment continues. And then, because we're assigning a Nil, and because a Nil denotes an absence of a value, the Array's default value ((Any)) is copied into the Scalar instead of the Nil.
On to the sub case...
sub foo {}
&foo = {} # Cannot modify an immutable Sub (&foo)
&foo := {} # Cannot use bind operator ...
While a sub foo declaration generates an &foo identifier, it is deliberately neither assignable nor bindable. If you want a Callable variable, you must declare one using ordinary variable declaration.
Unbind or undefine a variable
You can't unbind variables in the sense of leaving them bound to nothing at all. (In other words, Raku avoids the billion dollar mistake.) In some cases you can rebind variables.
In some cases you can bind or assign an undefined value to a variable. If it's not a scalar variable then that's like the # variable example covered above. The scalar cases are considered next.
An example of the binding case:
my $foo := Any;
say $foo.defined; # False
say $foo; # (Any)
say $foo.VAR.WHAT; # (Any)
We'll see what the .VAR is about in a moment.
The assignment case:
my $foo = Any;
say $foo.defined; # False
say $foo.WHAT; # (Any)
say $foo.VAR.WHAT; # (Scalar)
It's important to understand that in this case the $foo is bound to a Scalar, which is a container, which is most definitely "defined", for some definition of "defined", despite appearances to the contrary in the say $foo.defined; line.
In the say $foo.WHAT; line the Scalar remains hidden. Instead we see an (Any). But the (Any) is the type of the value held inside the Scalar container bound to $foo.
In the next line we've begun to pierce the veil by calling .VAR.WHAT on $foo. The .VAR gets the Scalar to reveal itself, rather than yielding the value it contains. And so we see the type Scalar.
But if you call .defined on that Scalar it still insists on hiding!:
my $foo;
say $foo.VAR.defined; # False
say $foo.VAR.DEFINITE; # True
(The only way to force Raku to tell you the ultimate truth about its view of definiteness is to call the ultimate arbiter of definiteness, .DEFINITE.)
So what are the rules?
The compiler will let you assign or bind a given new value or container to a variable, if doing so is valid according to the original variable declaration.
Assigning or binding an undefined value follows the same rules.
Binding
All variables must be bound by the end of their declaration.
If a variable's declaration allows an undefined value to be bound/assigned to that variable, then the variable can be undefined in that sense. But in all other circumstances and senses variables themselves can never be "unbound" or "undefined".
Binding is about making a variable correspond to some container or value:
Variables with # and % sigils must be bound to a container (default Array and Hash respectively).
Variables with the $ sigil must be bound to either a container (default Scalar) or a value.
Variables with the & sigil must be bound to a Callable value or a Scalar constrained to contain a Callable value. (The & sigil'd variable that's visible as a consequence of declaring a sub does not allow rebinding or assignment.)
Assignment
Assignment means copying a value into a container.
If a variable is bound to a container, then you can assign into it, provided the assignment is allowed by the compiler according to the original variable declaration.
If a variable is not bound to a container, then the compiler will reject an assignment to it.
Scalar variables
If you use a scalar container as if it were a value, then you get the value that's held inside the container.
Binding a value (defined or undefined) to a scalar variable will mean it will stop acting as a container. If you then try to assign to that variable it won't work. You'd need to rebind it back to a container.
Footnotes
[1] In this answer I've used the word "container" to refer to any value that can serve as a container for containing other values. For example, instances of Array, Hash, or Scalar.

How to define variable names dynamically in Perl 6?

I have a name which I'd like to give to a variable, in another string variable:
my $name = '$a'; or simply my $name = 'a'; How to make the variable and to use it? I mean something like this (but it doesn't work):
my $name = '$a';
my {$name} = 1; # Doesn't work
say $a; # should be 1
A more general case. I have a list of variable names, say my #names = '$aa' ... '$cc'; How to declare and use the variable, whose name will be e.g. #names[2]?
According to documentation the lexical pad (symbol table) is immutable after compile time. Also (according to the same docs) it means EVAL cannot be used to introduce lexical symbols into the surrounding scope.
I suggest you use package variables, instead of lexical variable as suggested in the comments.
However, a workaround is possible: You can create your own lexical pad at run time (for the module requiring) using for example require MODULE:
my $name = '$a';
spurt 'MySymbols.pm6', "unit module MySymbols; use v6; my $name = 1; say \"\\$name = $name\"";
use lib '.';
require MySymbols;
Output:
$a = 1
Lexical scopes are immutable, but the way you would do it is ::($name) or MY::($name).
my $a; # required or it will generate an error
my $name = '$a';
::($name) = 1;
say $a; # 1
MY::($name) = 2;
say $a; # 2
sub foo ($name,$value) { CALLER::MY::($name) = $value }
foo($name,3);
say $a; # 3

How to declare a data member reference in tclOO

I am trying to hold a reference to a variable as a data member in tclOO. Is there any construct that can simulate the upvar command that is used inside functions.
oo::class create TestClass {
variable refToVar
constructor {varRef} {
set varRef [string range $varRef 1 [expr [string length $varRef] -1]]
# upvar $varRef temp
# set refToVar $temp
upvar $varRef refToVar
}
method getRefToVar {} {
return $refToVar
}
method setRefToVar {value} {
set refToVar $value
}
}
proc testProc {varRef} {
set varRef [string range $varRef 1 [expr [string length $varRef] -1]]
upvar $varRef temp
set temp 5
}
puts "start"
set x 100
puts $x
puts "proc test"
testProc {$x}
puts $x
puts "tclOO test"
TestClass create tst {$x}
puts [tst getRefToVar]
tst setRefToVar 20
puts [tst getRefToVar]
puts $x
Basically i want to achieve the same behaviour with the oo::class that I am doing with the proc.
The equivalent is upvar. However you need to run the upvar in the right context, that of the object's state namespace and not the method (because you want refToVar to be by the overall object) because upvar always makes its references from in the current stack context, which means local variables in both cases by default.
TclOO provides the tools though.
my eval [list upvar 2 $varref refToVar]
It's a 2 because there's one level for my eval and another level for the method. MAKE SURE that you only refer to variables in a namespace (global variables are in the global namespace) this way or you'll have pain. It's probably not a good idea to keep references to variables around inside an object as they can be run from all sorts of contexts, but it should work.
You can also use the namespace upvar command inside that generated my eval to do the same sorts of thing, since anything you can write that is sensible can be described using namespace/varname coordinates instead of stack-index/varname coordinates.
[EDIT]: In fact, Tcl takes care to avoid the evil case, and throws an error if you try. Here's a boiled-down version of the class:
oo::class create Foo {
constructor v {
# This is done like this because this sort of operation is not affected
# by the 'variable' declaration; it's a bit unusual...
my eval [list upvar 2 $v ref]
}
variable ref
method bar {} {
# Just some normal usage
puts $ref
}
}
Let's show this working normally:
% set x 123
123
% set y [Foo new x]
::oo::Obj12
% $y bar
123
% incr x
124
% $y bar
124
OK, that all looks good. Now, let's go for attaching it to a local variable:
proc abc {} {
set x 234
set y [Foo new x]
# Try the call
$y bar
incr x
$y bar
# Try returning it to see what happens with the lifespan
return $y
}
But calling it doesn't work out:
% abc
bad variable name "ref": can't create namespace variable that refers to procedure variable
% puts $errorInfo
bad variable name "ref": can't create namespace variable that refers to procedure variable
while executing
"upvar 2 x ref"
(in "my eval" script line 1)
invoked from within
"my eval [list upvar 2 $v ref]"
(class "::Foo" constructor line 1)
invoked from within
"Foo new x"
(procedure "abc" line 3)
invoked from within
"abc"
So there you go; you can link an external global (or namespace) variable easily enough into an object, but it had better not be a local variable. It might be possible to do extra work to make using a local variable that is actually an upvar to a global variable work, but why would you bother?
Donal has answered your question, but there is a better way to do it.
oo::class create TestClass {
variable varRef
constructor args {
lassign $args varRef
}
method getRefToVar {} {
upvar 0 $varRef refToVar
return $refToVar
}
method setRefToVar {value} {
upvar 0 $varRef refToVar
set refToVar $value
}
}
Here, you supply the TestClass object with the qualified name of the variable, like ::x for the global variable x, or ::foobar::x for the x variable in the foobar namespace. You save this name in the instance variable varRef.
When you want to read from or write to this variable, you first create a local reference to it:
upvar 0 $varRef refToVar
This means that in the method where you are invoking this command, refToVar is a reference or alias to the variable whose name is stored in varRef.
You can do the same thing in a command procedure:
proc testProc {varRef} {
upvar 0 $varRef refToVar
set refToVar 5
}
Testing it:
puts "start"
set x 100
puts $x
puts "proc test"
testProc ::x
puts $x
puts "tclOO test"
TestClass create tst ::x
puts [tst getRefToVar]
tst setRefToVar 20
puts [tst getRefToVar]
puts $x
Note how the names are written differently.
If you somehow don't know the qualified name of the variable, this should be helpful:
TestClass create tst [namespace which -variable x]
BTW: you don't have to write
string range $varRef 1 [expr [string length $varRef] -1]
there is an abbreviated form for that:
string range $varRef 1 end
but you don't have to write that either: to remove zero or more dollar signs from the left end of a string, just
string trimleft $varRef \$
but you don't have to write that either: you don't need to add the dollar sign when passing a variable name:
proc bump varName {
upvar 1 $varName var
incr var
}
set x 10
# => 10
bump x
set x
# => 11
Documentation: expr, incr, lassign, namespace, proc, puts, set, string, upvar

Get input and pass variable from an if statement with Haskell

Here is a simplified version of the code I'm working on.
main :: IO ()
main = do
args <- getArgs
if null args
then putStr "> " ; userInput <- getLine
else userInput <- readFile $ head args
let conclusion = userInput
This won't work without do notation, the variable won't pass to conclusion below when I do use it, and the putStr, which I'm trying to use to create a kind of prompt, just makes it mad.
Is there something that I'm forgetting to add somewhere?
There are a few problems here. First, you need to include do after then and else:
if null args
then do putStr "> " ; userInput <- getLine
else do userInput <- readFile $ head args
if in do notation is the same as if everywhere else; you have to put an expression after then and else, not statements, and you need do to turn a bunch of statements into an expression. This still isn't quite valid, though; the last statement in a do block must be an expression, but you have a bind here. After all, every statement has to have a result value, but a bind has none.
The second problem is, as you've observed, that this introduces a new scope, and so you can't access variables you bind from outside. This makes sense if you think about it; after all, you could bind the variable on one side and not the other. The solution is to simply move the bind outside the if:
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do putStr "> " ; getLine
else readFile $ head args
let conclusion = userInput
So, the action whose result we bind to userInput is still computed depending on the result of null args, but we bind the variable outside the conditional.
Note that I didn't add a do to the else branch this time; it's not required, since there's only a single expression there. (It's still valid, but it's unidiomatic to use do when it's not necessary.)
This code still won't work unless you put something after the let conclusion = userInput line (since, like I said, do blocks must end with an expression), but presumably you already have code there.
As an additional note, you should avoid using functions like head and tail; head is a partial function (not defined for every argument — head [] will produce an error), and those are generally considered unidiomatic. You should use pattern-matching instead, like this:
userInput <- case args of
[] -> do putStr "> " ; getLine
fileName:_ -> readFile fileName
This is just like the pattern-matching used when defining a function, but for a single value rather than any number of arguments.
Any variable bindings you do in the then and else blocks won't be visible in the outer scope, so you need to bind the result from the if clause itself.
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do
putStr "> "
getLine
else readFile $ head args