Common Lisp THE gives no compiler warnings - common-lisp

From the examples given for the THE function (http://clhs.lisp.se/Body/s_the.htm) when i change the following form
(the (values integer float) (truncate 3.2 2))
to
(the (values integer integer) (truncate 3.2 2))
I still don't get any compiler warnings, whereas (the integer 1.2) gives
;Compiler warnings :
; In an anonymous lambda form at position 0: Type declarations violated in (THE INTEGER 1.2)
Can some one explain why the above doesn't produce warnings? I test these on CCL.

You have misunderstood what the does. The specification tells you in so many words:
the specifies that the values returned by form are of the types specified by value-type. The consequences are undefined if any result is not of the declared type.
(My emphasis.)
In other words, what the does is to allow you to say to the compiler 'I undertake that these things have these types and you may compile appropriate code for that, with no checks needed; if that's not true then I fully accept that you may need to set my hair on fire and gouge out my one remaining eye'.
Now, famously, CMUCL and its derivatives such as SBCL take a rather different approach to type checking. From the SBCL manual:
The SBCL compiler treats type declarations differently from most other Lisp compilers. Under default compilation policy the compiler doesn’t blindly believe type declarations, but considers them assertions about the program that should be checked: all type declarations that have not been proven to always hold are asserted at runtime.
Thus the system treats the as an assertion about types which, if it is not already known to be true, must be checked. This is, I think, conformant, since 'unspecified consequences' can obviously include 'raising an exception in a nice way' (personally I prefer eye-gouging compilers but that's just me).
But if you want to write portable code, you should not assume that the does this. Rather you need either to accept the risks that it does not, or use some form like check-type or assert with a type check as the thing you are asserting.

Related

Why do we use [1] behind an order by clause in xquery expressions?

SELECT xText.query (' let $planes := /planes/plane
return <results>
{
for $x in $planes
where $x/year >= 1970
order by ($x/year)[1]
return ($x/make, $x/model,$x/year )
}
</results>
')
FROM planes
In this code, what is the purpose of [1] in line order by ($x/year)[1]
I have tried to execute this code without using [1] behind order by clause. Then this error has occurred.
XQuery [planes.xtext.query()]: 'order by' requires a singleton (or empty sequence), found operand of type 'xtd:untypedAtomic*'
XQuery 1.0 defined an option called "static type checking": if this option is in force, you need to write queries in such a way that the compiler can tell in advance ("statically") that the result will not be a type error. The operand of "order by" needs to be a singleton, and with static type checking in force, the compiler needs to be able to verify that it will be a singleton, which is why the [1] has been added. It would have been better to write exactly-one($x/year) because this doesn't only keep the compiler happy, it also demands a run-time check that $x/year is actually a singleton.
Very few XQuery vendors chose to implement static type checking, for very good reasons in my view: it makes queries harder to write, and it actually encourages you to write things like this example that do LESS checking than a system without this "feature".
In fact, as far as I know the only mainstream (non-academic) implementation that does static type checking is Microsoft's SQL Server.
Static type checking should not be confused with optimistic type checking where the compiler tells you about things that are bound to fail, but defers checking until run-time for things that might or might not be correct.
Actually the above is a bit of a guess. It's also possible that some <plane> elements have more than one child called <year>, and that you want to sort on the first of these. That would justify the [1] even on products that don't do static type checking.
The [1] is a predicate that is selecting the first item in the sequence. It is equivalent to the expression [position() = 1]. A predicate in XPath acts kind of like a WHERE clause in SQL. The filter is applied, and anything that returns true is selected, the things that return false are not.
When you don't apply the predicate, you get the error. That error is saying that the order by expects a single item, or nothing (an empty sequence).
At least one of the plane has multiple year, so the predicate ensures that only the first one is used for the order by expression.

Does Closure support JSDoc array syntax like `string[]`?

I am having trouble finding out whether Closure supports JSDoc array syntax such as string[].
I don't see it documented on https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System#user-content-the-javascript-type-language . However, JSDoc supports it, and it has been around a while, so I'm surprised Closure wouldn't support it also.
(JSdoc implies it is not supported in Closure per https://jsdoc.app/tags-type.html , and mentions this in its catharsis type parser: https://github.com/hegemonic/catharsis , but I didn't know if this could be outdated info.)
If it is supported, I'd also like to know whether the optional = can be added immediately after it (without surrounding the previous expression in parentheses).
(As a bonus, I'd like to know whether the Record Type can have optional keys in Closure as through {key?: number}.)
JSDocs and Closure Compiler have their differences. Use the Closure documentation for details.
The type of an array of strings in closure is Array<string>.

MPI_Comm_dup() not working when sending MPI_COMM_NULL as argument

Somewhere I used
MPI_Comm_dup(row_comm, &bigger_row_comm);
and I noticed it caused 'fatal' error when row_comm was equal to MPI_COMM_NULL. I changed it with
if (row_comm != MPI_COMM_NULL)
MPI_Comm_dup(row_comm, &bigger_row_comm);
else
bigger_row_comm = MPI_COMM_NULL;
Now it works. I use MPICH and found this in its documentation in the entry for MPI_Comm_dup:
A common error is to use a null communicator in a call (not even allowed in MPI_Comm_rank).
I wonder if this behavior is standard and I should expect other implementations to do the same. Why haven't they just handled it like I did? One expects the duplicate of MPI_COMM_NULL to be a MPI_COMM_NULL.
The MPI standard does not specify what MPI_Comm_dup shall do when called with an null communicator (see section 6.4.2). Therefore, one cannot assume that such a call is allowed, especially since MPI_COMM_NULL is defined as "the value used for invalid communicator handles".
For what it's worth, OpenMPI 4.0.1 also treats the call as an error.

type declaration of arrays

I've a very big array composed of only nil s and t s .
My questions is; does it make sense for the compiler to make type declaration within a function that handles this specific type of array. If so what should the declaration look like?
For example:
(defun foo(my-array)
(declare (type (array ?????) my-array))
....
First notice that in Common Lisp an array of type (array boolean) (where BOOLEAN is the applicable type) is not an array that just happens to contain only ts and nils, but an array that can only contain those, which is a property that has to be specified during creation of the array. Violating this will result in a run-time error or undefined behaviour depending on your safety level.
I don't think there is much point in specifying the type at function level, since I don't believe there are any applicable optimizations. You might consider using bit-vectors, which are at least tightly packed and allow the use of fast bit processing instructions. That is, if your data is representable in one dimension, since I am not sure how much those apply for multidimensional (array bit) arrays.

Behaviour of non-const int pointer on a const int

#include<stdio.h>
int main()
{
const int sum=100;
int *p=(int *)∑
*p=101;
printf("%d, %d",*p,sum);
return 0;
}
/*
output
101, 101
*/
p points to a constant integer variable, then why/how does *p manage to change the value of sum?
It's undefined behavior - it's a bug in the code. The fact that the code 'appears to work' is meaningless. The compiler is allowed to make it so your program crashes, or it's allowed to let the program do something nonsensical (such as change the value of something that's supposed to be const). Or do something else altogether. It's meaningless to 'reason' about the behavior, since there is no requirement on the behavior.
Note that if the code is compiled as C++ you'll get an error since C++ won't implicitly cast away const. Hopefully, even when compiled as C you'll get a warning.
p contains the memory address of the variable sum. The syntax *p means the actual value of sum.
When you say
*p=101
you're saying: go to the address p (which is the address where the variable sum is stored) and change the value there. So you're actually changing sum.
You can see const as a compile-time flag that tells the compiler "I shouldn't modify this variable, tell me if I do." It does not enforce anything on whether you can actually modify the variable or not.
And since you are modifying that variable through a non-const pointer, the compiler is indeed going to tell you:
main.c: In function 'main':
main.c:6:16: warning: initialization discards qualifiers from pointer target type
You broke your own promise, the compiler warns you but will let you proceed happily.
The behavior is undefined, which means that it may produce different outcomes on different compiler implementations, architecture, compiler/optimizer/linker options.
For the sake of analysis, here it is:
(Disclaimer: I don't know compilers. This is just a logical guess at how the compiler may choose to handle this situation, from a naive assembly-language debugger perspective.)
When a constant integer is declared, the compiler has the choice of making it addressable or non-addressable.
Addressable means that the integer value will actually occupy a memory location, such that:
The lifetime will be static.
The value might be hard-coded into the binary, or initialized during program startup.
It can be accessed with a pointer.
It can be accessed from any binary code that knows of its address.
It can be placed in either read-only or writable memory section.
For everyday CPUs the non-writeability is enforced by memory management unit (MMU). Messing the MMU is messy impossible from user-space, and it is not worth for a mere const integer value.
Therefore, it will be placed into writable memory section, for simplicity's sake.
If the compiler chooses to place it in non-writable memory, your program will crash (access violation) when it tries to write to the non-writable memory.
Setting aside microcontrollers - you would not have asked this question if you were working on microcontrollers.
Non-addressable means that it does not occupy a memory address. Instead, every code that references the variable (i.e. use the value of that integer) will receive a r-value, as if you did a find-and-replace to change every instance of sum into a literal 100.
In some cases, the compiler cannot make the integer non-addressable: if the compiler knows that you're taking the address of it, then surely the compiler knows that it has to put that value in memory. Your code belongs to this case.
Yet, with some aggressively-optimizing compiler, it is entirely possible to make it non-addressable: the variable could have been eliminated and the printf will be turned into int main() { printf("%s, %s", (b1? "100" : "101"), (b2? "100" : "101")); return 0; } where b1 and b2 will depend on the mood of the compiler.
The compiler will sometimes take a split decision - it might do one of those, or even something entirely different:
Allocate a memory location, but replace every reference with a constant literal. When this happens, a debugger will tell you the value is zero but any code that uses that location will appear to contain a hard-coded value.
Some compiler may be able to detect that the cast causes a undefined behavior and refuse to compile.

Resources