What's different between in LogicalCorrelate and LogicalJoin? - apache-calcite

When I was reading the Calcite Code, I found the 'join' has different types, the LogicalCorrelate and LogicalJoin. What is the difference between these types?

Related

How to construct expression templates from operations on fundamental data types?

I'm trying to build expression templates from maths operations in order to correctly sequence unsequenced operations (such as opertor+).
The reason is because operator co_await with operator+ appears to be unsequenced (resulting in incorrect results from generators/yielding tasks). See here C++20 Coroutines, Unexpected reordering of await_resume, return_value and yield_value.
If I can use expression templates on primitive data types I can manually sequence the execution using expression templates. This is mainly an excercise to determine whether its possible (not whether its a good idea) to detemine whether a possible work around for the issue exists.
If its not possible to get global operators overloaded for primative types then does anybody have any ideas how to inject expression templates into existing operator based maths code.
Ongoing Research
Operators require atleast 1 class type for overloads:
why C++ operator overloading requires "having at least one parameter of class type"?
So, I cannot do it for fundamental data types.
So it transforms this questions focus to be around other ways to transform fundamental data type expressions into expression templates.
As per comment below from Peter.
As the arguments of operator+(a,b) are unsequenced this approach will not work :(

How to deal with different data types when parsing a general CSV read function? (without specifying them explicitly)

How to deal with different data types when reading in data from an arbitrary CSV?
That is, how to deal with the different data types without specifying them explicitly?
You need to use std::any - See http://en.cppreference.com/w/cpp/utility/any.
Store the values into an std::vector<std::vector<std::any>>

boost serialization data type compatibility

I need to serialize/deserialize certain data structures between two identical applications, but built using different compilers.
Consider primitive datatypes. Boost documentation mentions that in order to ensure compatibility you need to use the numeric types in <boost/cstdint.hpp>. So did I understand it right that I can't simply declare int number;, but rather I should do something like int16_t number;?

A compile time ordering on types

I've been looking for a way to get an ordering on types at compile time. This would be useful, for example, for implementing (efficient) compile-time type-sets.
One obvious way to do it would be if there were a way to map every type to a unique integer. An answer to a previous question on that topic succinctly captures why that's difficult, and it seems like it would apply equally to any other way of trying to get an ordering:
the compiler has no way of knowing all compilation units and the linker has no concept of a type
Indeed, the challenge to the compiler would be considerable: it has to make sure that, in any invocation, for any source file, it returns the same integer for a given type / it returns the same ordering between any two given types, but at the same time, the universe of types is open and it has no knowledge of any types outside of the current file. A hard problem.
The idea I had is that types have names. And by the laws of C++, as far as I know the fully qualified name of a type must be unique across the entire program, otherwise you will get errors or undefined behaviour of some sort or another.
If two types have the same name, then they are the same type.
If two types are the same type, then either they have the same name, or they are typedefs for one another. The compiler has full knowledge of typedefs.
Names are strings, and strings have an ordering. So if I have it right, you could define a globally consistent ordering on types based on their names. More specifically, the ordering between any two types would be the ordering between the names of the types with the typedefs fully resolved. (Having a type behave differently from its typedefs would be problematic.)
Of course, standard C++ doesn't have any facilities for retrieving the names of types.
My questions are:
Do I have anything wrong? Are there any reasons this wouldn't, in theory, work?
Are there any compilers which give you access to the names of types (and ideally their typedef-resolved forms) at compile time as a language extension?
Is there any other way it could be done? Are there any compilers which do?
(I recognize that it's not polite to ask more than one question in the same question, but it seemed strange to post three separate questions with the same basic throat-clearing preceding them.)
the fully qualified name of a type must be unique across the entire program
But of course, that's only true if you consider seperate anonymous namespaces in different translation units to have different names in some sense, and have some way to figure out what they are.
The only sense in which I'm aware they really do have different names is in mangled linker symbols; you may (depending on the compiler) be able to get that from type_info::name(), but it isn't guaranteed, is limited to types with RTTI, and anyway doesn't seem to be declared as a constexpr so you can't use the value at compile time.
The ordering produced by type_info::before() naturally has the same limitations.
Out of interest, what are you trying to achieve with your compile-time type ordering?

Dealing with circular dependencies in OCaml

I'm writing an interpreter for an experimental language. Three of the main constructs of the language are definitions, statements, and expressions. Definitions can contain statements and expressions, statements can contain definitions and expressions, and one kind of expression can contain statements. I represent all of these using union types so I can easily use pattern matching on them. Ideally, I would like to put the code for these in different files, but OMake complains about circular dependency issues. As far as I know, circular type definitions across modules are not allowed.
The only way I know of to solve this is to define all three types at once:
type defn = ...
and stmt = ...
and expr = ...
It seems like this requires all the code for types to be in the same file. Is there any way around this? How do you deal with circular definitions in your code?
Recursive definitions need to appear in the same file. If you want to separate definitions, statements, and expressions into separate modules, you can do so using recursive modules, but they will still need to appear in the same file. DAG-ifying inter-file dependencies is one of the annoyances of OCaml.
This is easily solved by parameterizing your types over the types they refer to:
type ('stmt, 'expr) defn = ...
type ('defn, 'expr) stmt = ...
type ('defn, 'stmt) expr = ...
This technique is called "untying the recursive knot" (in reference to Gordian's knot) and was described in an OCaml Journal article.
Cheers,
Jon Harrop.
Another solution often used is to abstract the types in the interfaces. Since the types are abstract in the interfaces, these interfaces are not recursively dependent. In the implementations, you can specify the types, and since the implementations depend only on the interfaces, they are not recursive either.
The only problem is that, with this solution, you cannot anymore pattern-matching on these types outside of their implementation.
Personally, but it is probably a matter of taste, I like to have all the types of my program defined in one module (I think it helps in the readability of the program). So, this restriction of OCaml is not really a problem for me.