how to print the type of an expression in Frege - frege

In the interactive shell and (online) REPL I can enter
:type 1
to find out the type of the expression "1". Is there any function that I can use from code to achieve the same effect?

There is no easy way to do this at this time.
However, the REPL is itself written in Frege, so it certainly is possible.
The "trick" is to construct a complete program, like
module Foo where { x = 1 }
and run it through the first compiler passes, up to and including the type checking pass. After that, one could query the symbol table for the top level symbol x and its type.

Related

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.

Use of mathematical operator at start of line

I have a basic question for my general knowledge of Kotlin concerning the mathematical operators:
I was writing an equation and I mistakenly put the plus sign on the second line which caused my equation not to work as on the examples below:
val x = 2 + 3 //x = 5 CORRECT
val x = 2 +
3 //x = 5 CORRECT
val x = 2
+ 3 //x = 2 WRONG
My question is: why Kotlin is not showing any error message on the last example? How is Kotlin interpreting the line "+3"?
val x = 2 is correct expression, so compiler uses it as complete expression.
+ 3 is correct expression although it doing nothing.
val x = 2 + is uncompleted expression - the compiler is trying to complete it using the next line.
This is an unfortunate result of the way Kotlin assumes a semicolon at the end of lines.
In languages like Java, every statement must end with a semicolon, so there's no ambiguity.
Kotlin allows you to omit semicolons, which can be handy.  But it's a bit over-eager: it infers one at the end of every line that would make sense on its own, ignoring the following lines.  This is rather annoying to those of us who like to put operators at the start of a line, not the end…
Most of the time, the following line won't make sense on its own, so you get a compiler error to warn you of the issue.  Unfortunately, you've found one of the rare cases where the following line is valid, and so there's no error!  (Kotlin has a unary plus to match its unary minus, so +3 is a number just like -4.  And a number on its own is a valid expression.  Kotlin calculates the value, and then discards it.)
The solutions are:
Put the whole expression on the one line.  (Which is unwieldy if it's long!)
Put the operator at the end of the previous line.  (Which is clearly what the language designers expect, but some of us find less logical and less clear.)
Prevent the first line from making sense on its own.
The best way I've found to do that last one is with parens:
val x = (2
+ 3)
It looks awkward in a very short expression, but it works reasonably well on longer ones — not ideal, but necessary unless/until Kotlin gets smarter about where to assume semicolons…

Is it possible to make Stata throw an error by default when a global macro is not defined, instead of a missing string?

A feature of Stata that is sometimes inconvenient is that calling a non-defined macro returns the missing value . [edit: Stata actually returns a missing string "", not a numerical missing value], instead of throwing an error.
A piece of code, whose correct execution requires the definition of the macro, may just run giving incorrect results if the macro name is misspelled.
E.g.: having defined
global $options = , vce(robust), when
afterwards one writes reg y x $opt instead of reg y x $options the program runs anyway and it may be difficult to realise that the vce() option was not considered.
Is there any way to force Stata to issue an error in this case or is there some useful trick/best practice that can be used to reduce the risk of incurring this sort of mistake?
The feature is described incorrectly. A macro that is undefined is evaluated as an empty string, conventionally written "", i.e. the delimiters " " contain nothing, or -- if you prefer -- nothing is contained between them.
A macro that is undefined is not ever evaluated as numeric system missing, written as a period . (call it dot or stop if you want).
You would see system missing if the macro were set to contain something else that was system missing, which is entirely different. Saved results from programs, for example, might be system missing.
One way to understand this is that macros in Stata contain strings, not numeric values; the fact that some macros have a numeric interpretation is something else. So, an undefined macro is evaluated as an empty string.
Stata programmers learn to use this feature constructively as a way of allowing defaults when macros are undefined and other choices when they are defined.
You are correct that the feature is a source of bugs, as when a spelling mistake leads Stata to see a name that isn't defined and just ignores the reference. The bug is still the programmer's bug, not Stata's.
So, what can you do, apart from check your code as usual? You can always check whether a macro is defined, as in
if "$options" == "" {
* do something
}
else {
* do something else
}
Conversely,
if "$options" != ""
is a test for content.
Alternatively, you could use string scalars. Here is an experiment:
. sysuse auto, clear
(1978 Automobile Data)
. scalar foo = ", meanonly"
. summarize mpg `=scalar(foo)'
. ret li
scalars:
r(N) = 74
r(sum_w) = 74
r(sum) = 1576
r(mean) = 21.2972972972973
r(min) = 12
r(max) = 41
. summarize mpg `=scalar(bar)'
bar not found
Variable | Obs Mean Std. Dev. Min Max
-------------+---------------------------------------------------------
mpg | 74 21.2973 5.785503 12 41
In this case, there was an error message when an undefined scalar was referred to, but the command was executed any way.
Personally, as a long-term (1991- ) and high intensity Stata user, I just use macros routinely and regard being occasionally bitten by bugs of this kind as a very small price to pay for that. I have not ever used string scalars in this sense before trying to answer this question.
It's a different argument, but I regard using global macros in this way as poor programming style. There are general arguments across programming for minimizing the use of globally declared entities. Local macros are the beasts of choice.

How to tell if an identifier is being assigned or referenced? (FLEX/BISON)

So, I'm writing a language using flex/bison and I'm having difficulty with implementing identifiers, specifically when it comes to knowing when you're looking at an assignment or a reference,
for example:
1) A = 1+2
2) B + C (where B and C have already been assigned values)
Example one I can work out by returning an ID token from flex to bison, and just following a grammar that recognizes that 1+2 is an integer expression, putting A into the symbol table, and setting its value.
examples two and three are more difficult for me because: after going through my lexer, what's being returned in ex.2 to bison is "ID PLUS ID" -> I have a grammar that recognizes arithmetic expressions for numerical values, like INT PLUS INT (which would produce an INT), or DOUBLE MINUS INT (which would produce a DOUBLE). if I have "ID PLUS ID", how do I know what type the return value is?
Here's the best idea that I've come up with so far: When tokenizing, every time an ID comes up, I search for its value and type in the symbol table and switch out the ID token with its respective information; for example: while tokenizing, I come across B, which has a regex that matches it as being an ID. I look in my symbol table and see that it has a value of 51.2 and is a DOUBLE. So instead of returning ID, with a value of B to bison, I'm returning DOUBLE with a value of 51.2
I have two different solutions that contradict each other. Here's why: if I want to assign a value to an ID, I would say to my compiler A = 5. In this situation, if I'm using my previously described solution, What I'm going to get after everything is tokenized might be, INT ASGN INT, or STRING ASGN INT, etc... So, in this case, I would use the former solution, as opposed to the latter.
My question would be: what kind of logical device do I use to help my compiler know which solution to use?
NOTE: I didn't think it necessary to post source code to describe my conundrum, but I will if anyone could use it effectively as a reference to help me understand their input on this topic.
Thank you.
The usual way is to have a yacc/bison rule like:
expr: ID { $$ = lookupId($1); }
where the the lookupId function looks up a symbol in the symbol table and returns its type and value (or type and storage location if you're writing a compiler rather than a strict interpreter). Then, your other expr rules don't need to care whether their operands come from constants or symbols or other expressions:
expr: expr '+' expr { $$ = DoAddition($1, $3); }
The function DoAddition takes the types and values (or locations) for its two operands and either adds them, producing a result, or produces code to do the addition at run time.
If possible redesign your language so that the situation is unambiguous. This is why even Javascript has var.
Otherwise you're going to need to disambiguate via semantic rules, for example that the first use of an identifier is its declaration. I don't see what the problem is with your case (2): just generate the appropriate code. If B and C haven't been used yet, a value-reading use like this should be illegal, but that involves you in control flow analysis if taken to the Nth degree of accuracy, so you might prefer to assume initial values of zero.
In any case you can see that it's fundamentally a language design problem rather than a coding problem.

How to suppress VB's "Iteration variable shouldn't been used in lambda expression"

I'm working with LINQ in VB.NET and sometimes I get to a query like
For i = 0 To 10
Dim num = (From n In numbers Where n Mod i = 0 Select n).First()
Next
and then it comes the warning "Using the iteration variable in a lambda expression may have unexpected results. Instead, create a local variable within the loop and assign it the value of the iteration variable."
I know it's not a good practice to use the iteration variable in the lambda expression, because lambda expressions are evaluated only when needed. (This question is about that)
Now my question is, how to suppress this warning in cases where the expression is evaluated in-place, with constructions like First(), Single(), ToList(), etc. (It's only a warning, but i like my code clean.)
(Declaring a local variable and passing the iteration variable to it is an option, but I'm looking for a clean solution.)
In this particular case where the lambda is evaluated immediately, then you can safely eliminate the warning by moving the declaration of the iteration variable outside the for loop.
Dim i = 0
For i = 0 To 10
...
I do want to stress though that this only works if the lambda does not escape the for loop (true for your scenario).
Also here is a detailed link to an article I wrote on this warning (why it exists, how to avoid it, etc ...)
http://blogs.msdn.com/b/jaredpar/archive/2007/07/26/closures-in-vb-part-5-looping.aspx