Erlang - checking for unbound variables - variables

Is there any way to know if a certain variable has been bound or not after an expression has been evaluated ?
My code:
{ok, After} = ts_dynvars:lookup(last, DynVars),
what I need to know if whether there is any "After" to work with or not. Perhaps that "ok" can be put to use for my purpose ?
Thanks!

If you (try to) refer to an unbound variable in an expression, it's a compilation error. In particular, after
{ok, After} = ts_dynvars:lookup(last, DynVars),
there are only two possibilities: if the pattern matches, After is bound, and can be used; if it doesn't, an exception will be thrown, and code which tries to work with After will never be executed.
UPDATE:
are you telling me there is no way to branch code execution in the situation in which the pattern does not match
Of course there is:
case ts_dynvars:lookup(last, DynVars) of
{ok, After} -> ...;
_ -> ... %% or other patterns
end
but the compiler won't let you use After in other branches or after case (unless all branches bind After).
is this exception not catchable at all
It is:
try
{ok, After} = ts_dynvars:lookup(last, DynVars),
...
catch
_:_ -> ...
end
but again, you won't be able to use After in catch sections or after try ends (you can bind a new variable named After, of course).

3 possibilities:
After is not yet bound and the ts_dynvars:lookup/2 returns a result of
the form {ok,Value} then After is bound to Value (a copy is made)
and the program goes to the next line.
After is already bound and ts_dynvars:lookup/2 returns exactly {ok,After}: the pattern matches;
After keeps its value; and the program goes to the next line.
ts_dynvars:lookup/2 returns Ret that does not match {ok,After} as
described in the 2 previous lines. Then the execution stops and the
VM throws the exception {badmatch,Ret}. If the line is in a catch or
a try section, the process will continue, otherwise it will crash. The next
line of code (if any) will never be executed.

Related

Are closing brackets counted as statements in Statement Coverage? What about if they come after a return statement?

I'm doing a simple assignment where I have to go over test case coverage(statement coverage, path coverage, etc) of a function.
I've tried endlessly to add code here and StackOverflow won't accept it no matter how I format it, so I'll just explain a very simple example.
Let's say you get to an if statement that has a return statement inside it. In the line below the return line is the if's closing bracket '}'
My professor and our textbook have been pretty vague about what a statement is, but my understanding is that for a line of code to be a statement it has to perform some type of function such as assigning a value to a variable or being a conditional statement like an if or while loop.
So my questions are:
Does the closing bracket count as a statement? Or do they only count as a line?
When the computer is reading the code and hits the return statement, does it jump to the correct number of closing brackets before leaving the function and returning a value?
Closing brackets are not traditionally counted as statements.
Even if they follow a return (or any other kind of unconditional control transfer, e.g. goto to raise exception.).
A more interesting case is:
if (...) {
return;
x=1;
}
The x=1; statement can't get control. Test coverage should tell you it is uncovered because it never gets executed.
This example is exactly the same code, slightly reformatted:
if (...) {
return; x=1; }
Many test coverage tools will show you covered lines rather than covered code, so would mark the return line as covered. That's wrong; x=1; is still uncovered and the coverage display tool should make that clear.
This is especially important if you have a long source line which exits (e.g., by exception) in the middle:
x=foo().bar().baz();
If bar() throws an exception, then foo(). is covered, x=... is not, and baz() is not. This shows why line coverage, while common, can be very misleading.
Now consider this case:
if (a) {
...
if (b)
return;
}
c;
If a and b are true, the return statement executes. Control doesn't flow past the if (b) statement. If a is true and b is false... the return isn't executed and control flows past the if (b) to statement c;. In this case you can argue the } is "covered" even though it isn't a statement. A good coverage tool should show } c; as covered.

How to handle EOF with the scan_fmt crate?

With the scan_fmt crate, how do I handle EOF, when used with the scanln_fmt helpers? I want to do something like this where x is None if a empty line was provided:
let (isEOF, x) = scanln_fmt_some!("{d}");
How can I distinguish between empty new line input and EOF?
The scan_fmt crate does not expose a way to distinguish between EOF and other errors.
The macros only return either a (Option<X>, Option<Y>, ...) (as from scan[ln]_fmt_some) or a Result<(X, Y, ...), ScanError> (as from scan[ln]_fmt). And ScanError's contents seems to only explain what type failed to parse, but not why.

Cannot assign an if statement to a variable

The problem here is that I do not understand well the difference between statements and blocks in control flow.
Looking the ternary operator I can use it to assign a variable. But this is an operator, so it is like applying a function--isn't it?
> my $variable = True ?? 34 !! 42;
34
since in the raku documentation says:
if documentation
if
To conditionally run a block of code, use an if followed by a
condition. The condition, an expression, will be evaluated immediately
after the statement before the if finishes. The block attached to the
condition will only be evaluated if the condition means True when
coerced to Bool. Unlike some languages the condition does not have to
be parenthesized, instead the { and } around the block are mandatory:
do documentation
do
The simplest way to run a block where it cannot be a stand-alone statement is by writing do before it:
so this should work in both cases:
> my $variable = do {34};
34
> my $variable = if True {34;} else {43;}
===SORRY!===
Word 'if' interpreted as a listop; please use 'do if' to introduce the statement control word
------> my $variable = if⏏ True {34;} else {43;}
Unexpected block in infix position (two terms in a row)
------> my $variable = if True⏏ {34;} else {43;}
as said in the error I need to add the do:
> my $variable = do if True {34;} else {43;}
34
So the if really does not run the block...or what is the real problem here?
TL;DR: The actual difference is between statement and expression, not statement and block. do is a statement prefix that creates expressions.
if actually creates a statement (anything that is run in Raku is), however, what it's not is an expression. do is a statement prefix, and what it does is turn statements into expressions.
However, if is not really a first-class function that you can assign to a variable or handle around. Whenever you find pieces of syntax such as that one (or for, for instance), you need to prefix them with do to "expressionify" them.
say &say.^name;# OUTPUT: «Sub␤» say &do.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>␤Undeclared routine:␤...
say &if.^name; # OUTPUT: «===SORRY!=== Error while compiling <tmp>␤Undeclared routine:␤ if used at line 1␤␤»
So if, by itself, does not create a block, it does not create an expression, it simply creates a statement. You need to precede it with do if you want it to actually turn it into a expression. It does run the block that's behind it, however.
Let's go back to the original question, statements and blocks. Blocks are objects, first-class citizens. You can use them, apply them, pass them around.
my &ifs = { if $_ {34} else {43}};
ifs(True).say; # OUTPUT: «34␤»
Statements are throwaway blocks you simply run. In some cases, they are also expressions: they yield a result which, then, you can assign.
my &ifs = { if $_ {34} else {43}};
my $result = ifs(True).say; # OUTPUT: «34␤»
say $result; # OUTPUT: «True␤»
The ifs(True).say statement prints to output, it also produces a result that can be assigned. All three lines are also statements, and as a matter of fact, expressions too.
Some control structures, however, do not create expressions.
Some others do; for creates a expression; while does not.
if is an example of this. They don't produce a result. You use them for the side effects: running a statement (if true) or another (if not). You might turn them into a block, as above, and pass them around. Or you can just precede them with do and make them produce a throwaway result, which you can then use.
So it will very much depend on your actual use case. You can surround the if statement with curly braces and create a block; or you can simply use the result creating an expression. Or you might want to use it just for the side effects, doing nothing.

String replacement with .subst in a for loop

I'd like to make a string substitution in a for block using a named capture. I've expected to get the numbers 1,2,3 as output. But it is Nil for the first run, and then 1 and 2 for the 2nd and 3rd run. How do I use the .subst correctly in the loop construct? I see the same behavior when using a map construct instead the for loop. It does work as expected, if I replace with a fixed string value.
for <a1 b2 c3> -> $var {
say $var;
say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK
}
#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11
Output:
a1
Use of Nil in string context
in block at test3.pl6 line 3
b2
1
c3
2
]
TL;DR Defer evaluation of $<nr> until after evaluation of the regex. #JoKing++ suggests one way. Another is to just wrap the replacement with braces ({$<nr>}).
What happens when your original code calls subst
Before Raku attempts to call the subst routine, it puts together a list of arguments to pass to it.
There are two values. The first is a regex. It does not run. The second value is $<nr>. It evaluates to Nil because, at the start of a program, the current match object variable is bound to something that claims its value is Nil and any attempt to access the value of a key within it -- $<nr> -- also returns Nil. So things have already gone wrong at this point, before subst ever runs.
Once Raku has assembled this list of arguments, it attempts to call subst. It succeeds, and subst runs.
To get the next match, subst runs the regex. This updates the current match object variable $/. But it's too late to make any difference to the substitution value that has already been passed to subst.
With match in hand, subst next looks at the substitution argument. It finds it's Nil and acts accordingly.
For the second call of subst, $<nr> has taken on the value from the first call of subst. And so on.
Two ways to defer evaluation of $<nr>
#JoKing suggests considering use of S///. This construct evaluates the regex (between the first pair of /s) first, then the replacement (between the last pair of /s). (The same principle applies if you use other valid S syntaxes like S[...] = ....)
If you use subst, then, as explained in the previous section, Raku puts together the argument list for it before calling it. It finds a regex (which it does not run) and a closure (which it does not run either). It then attempts to call subst with those arguments and succeeds in doing so.
Next, subst starts running. It has received code for both the match (a regex) and the substitution (a closure).
It runs the regex as the matching operation. If the regex returns a match then subst runs the closure and uses the value it returns as the substitution.
Thus, because we switched from passing $<nr> as a naked value, which meant it got frozen into Nil, to passing it wrapped in a closure, which deferred its evaluation until $/ had been set to a match with a populated <nr> entry, we solved the problem.
Note that this only works because whoever designed/implemented subst was smart/nice enough to allow both the match and substitution arguments to be forms of Code (a regex for the match and ordinary closure for the substitution) if a user wants that. It then runs the match first and only then runs the substitution closure if it's been passed one, using the result of that latter call as the final substitution. Similarly, S/// works because that has been designed to only evaluate the replacement after it's first evaluated the substitution.

Why are there two ways of indicating error in Elixir?

Some Elixir functions have 2 variants for indicating error
Return a tuple e.g. File.open which returns something like {:ok, io_device} or {:error, posix}
Raise exception e.g. File.open!
My questions are:
What's the intention of having two ways?
Is one preferred over the other (like best practices)?
There are two ways of handling errors, because there are two types of errors:
the expected errors - like user providing bad data, etc. In that case you use the tuple-style return values to handle the error. This also forces the caller to consider the error case and handle it properly.
the truly unexpected exceptions - like a configuration file suddenly disappearing, that can't be recovered from and that there's not much to do beside crashing. In that case you raise an exception.
Because of those two ways, you extremely rarely find yourself in need of rescuing exceptions - where in other languages you would rescue an exception, in Elixir you avoid raising it in the first place, and rather return an ok/error tuple instead.
I'd say the tuple-style is superior, as it gives control to the caller - the caller can decide what to do with the error by either pattern matching on the return value in a case expression and handling both possibilities, or, ignoring the erroneous one, pattern matching directly on the ok tuple. The second one will convert the return value to a MatchError exception, should the unexpected error occur. You can see how the first style can be easily converted to the second one. That said many libraries provide "bang" functions that raise the error for ease of use and ability to provide better error messages than a plain MatchError does allow.
While the {:ok, value} is often paired with {:error, reason}, it's merely a convention. There are many APIs that return only :error without a reason, where the reason is obvious, there are also some that return something different in the successful case. The rule here is to provide an easy pattern match that is not order dependent. Let's see some examples:
{value, rest} | :error
That's a good choice, since the cases are easily distinguishable - this style is used, for example by Integer.parse/2. If the success condition has two return values and there's only one reason for failure, this style is recommended.
string | :error
This doesn't seem like a good idea, you'd either need to have a guard in the pattern match or be careful to match the :error atom first. Instead, one would wrap the success value in a {:ok, string} tuple for ease of use.