C++ provides `set_intersection` as well: http://en.cppreference.com/w/cpp/algorithm/set_intersection
108 karma · joined November 17, 2012
C++ provides `set_intersection` as well: http://en.cppreference.com/w/cpp/algorithm/set_intersection
Serialization is beyond the scope of what I am talking about. I am talking about reading bytes from a serial port.
> In that way, when using Async for network sockets, the SerialPortHW concept wouldnt be involved at all
But that is my whole point about Asio being split into smaller libraries such as Asio.Core, Asio.Network, and Asio.SerialPort. So you can use Asio.SerialPort without needing Asio.Network.
> in many occasions such extra async framework or the streams are not used.
You didn't read and write bytes to the serial port? What did you use it for?
> it would be in a different concept not included in the current project.
Its important for the library to implement the same "concepts"(or type requirements) for better consistency and composability(the only exception is iostreams which is horrible for both usability and implementations).
That's backwards. A SerialPort library would depend on Asio since it defines sync and async streams and the utilities built around that. It seems bad design for a SerialPort library to reimplement those basic utilities.
A dependency manager allows for finer modularity. So instead, Asio could be split into multiple libraries: Asio.Core, Asio.Serial, Asio.Network, etc. Its ok we have to bring in two smaller libraries instead of one large libary, since we have a dependency manager to handle this for us.
Also, a lack of a dependency manager in C++ has lead to developing of large monolithic libraries. So instead of managing dependencies, the library gives you everything plus the kitchen sink, so the user won't need to use another library. Of course, this is not scalable.
The other side-effect from a lack of a dependency manager in C++ is the developing of unnecessary header-only libraries(like Boost.Signals2). This just slows down compilation.
A real viable dependency manager in C++ will be a game changer, and recently. there is a lots of serious talk about it. In fact, there are like 3 difference talks that are directly related to dependency managing at C++Now 2015.
This is true. Sentences without correct grammar are unparseable(like "he jumped didn't far"). A lot of people seem to confuse semantic or logic issues with grammar issues.
#define IOD_DEFINE_SYMBOL(name) iod_define_symbol(name, _##name)
#define IOD_S(name) s::_##name
#define ZLANG_iod_define (IOD_DEFINE_SYMBOL)
#define ZLANG_iod_s (IOD_S)
And then compiling with `-DZLANG_NS=iod` you can call it like this: // Define symbols
$(define hello)
$(define message)
auto hello_api = make_api(
// The hello world procedure.
$(s hello) = [] () { return D($(s message) = "Hello world."); }
);
Also, ZLang can be supported without a need for a dependency on ZLang. struct square
{
int x;
};
struct rectangle
{
int x;
int y;
};
boost::variant<square, rectangle> to_shape(int x, int y)
{
if (x == y) return square(x);
else return rectangle(x, y);
}
std::vector<std::pair<int, int>> unknowns = {
{5, 4},
{3, 2},
{4, 4}
};
auto shapes = unknowns | boost::adaptors::transformed(boost::fusion::make_fused(to_shape));
Of course, the structs are not polymoprhic and can't be printed out. I just left that out because it requires a little more code to do that. Obviously with haskell its much less code.I would very much be interested in the dependently typed version.
http://pfultz2.github.io/Fit/doc/html/fix/
So you could implement a generic factorial like this:
auto factorial = fit::fix([](auto self, auto x) -> decltype(x)
{
return x == 0 ? 1 : x * self(x-1);
}); template<typename T>
std::pair<T, std::vector<std::string_view>>
tokenize_string(T &&str);
So then it uses `std::forward` to conditionally move the string for rvalues, and `T` will be a reference to the original string for lvalues.It may be more verbose in C++, but its not more complicated, and its definitely not "ridiculously" complicated.
> I just implemented something very similar in Common Lisp and it wound up being incredibly simple.
Maybe for you as a lisp programmer, but for me I find the lisp code incomprehensible.
Actually, pipable is very similiar to haskell's `$` function. So a similiar thing is done to improve readability of chaining functions in functional languages as well.
> At any rate, the thing that's strange about it is how verbose and hackish everything is. It's obvious the language wasn't designed to do anything like this, so the only way you can incorporate features like this is with unnecessarily obtuse and complex blocks of code.
How is the code obtuse and complex? I am using fairly straightforward techniques. I understand that I am working around the lack of perfect capturing for lambdas, but it is not complicated or clever the workaround.
It is really common for the `|` operator to be used for piping functions together. There are several libraries that support it: [Boost.Range](http://www.boost.org/doc/libs/1_56_0/libs/range/doc/html/ind...), [PStade Oven](http://p-stade.sourceforge.net/oven/doc/html/index.html), [Linq](http://pfultz2.github.io/Linq/), and [Streams](http://jscheiny.github.io/Streams/). Plus, its even being proposed as part of the ranges library in future C++: https://github.com/ericniebler/range-v3/blob/master/doc/D412...
So just as the bit shift operators in C++ also have the meaning of streaming in and out, the bitwise or also has the meaning of pipe, so this is should not at all be a suprise.
That doesn't sound like good C++. Making everything a pointer or implementing polymorphism through pointers makes the code harder to reason about, and makes tighter coupling between interfaces and implementations.
Futhermore, doing it by hand is not as simple, but still not very complicated. This just helps alleviate the boilerplate in defining pipable functions.
auto r = select(where(numbers, [](int x) { return x > 2; }), [](int x) { return x * x; });
Because of nesting this can be hard to read(and even write). If we can make the function pipable, the above can be written like this: auto r = numbers | where([](int x) { return x > 2; }) | select([](int x) { return x * x; });
Which it is easier to see what this does. So this blogpost goes over how to implement an utility that will take care of the boilerplate involved in writing a function that can be pipable.It does take advantage of a lot of C++14 features to implement this such as such as vardiac templates, rvalue reference, generic lambdas, and auto type deduction, but those feature actually make it simpler. I have in the past implemented something similar for C++03 and the code looks awful with way too much noise.
> this is madness.
Why do you consider this madness?
Maybe my mind has already been warped by C++.
auto q = LINQ(
from(z, boost::irange(1, std::numerical_limits<int>::max()))
from(x, boost::irange(1, z))
from(y, boost::irange(1, x))
where(x*x + y*y == z*z)
select(boost::fusion::make_vector(x, y, z))
);
for(auto&& x:q | linq::take(10)) std::cout << x << std::endl;
Hopefully, once we get ranges in the C++ standard library, we can add list comprehension to the language, perhaps something like this: auto q = [
for (z, std::irange(1, std::numerical_limits<int>::max()))
for (x, std::irange(1, z))
for (y, std::irange(1, x))
if (x*x + y*y == z*z)
boost::fusion::make_vector(x, y, z)
];
for(auto&& x:q | std::take(10)) std::cout << x << std::endl; vector<int> squareVec(const vector<int>& v)
{
return LINQ(from(i, v) select(i*i)) | linq::to_container;
}
And also filtering out odd elements: vector<int> squareVecFiltered(const vector<int>& v)
{
return LINQ(from(i, v) where(i % 2 == 0) select(i*i)) | linq::to_container;
}Which there is less of need for this, since we have better type deduction in C++11 and 14 as well.
However, searching a `std::vector` is not really part of its implementation. So, requiring every single range to overload an operator for trivial searching is not good, especially since there are only a few containers that have non-trivial searching.
Instead, the range-based find could be specialized for containers that have non-trivial searching instead(perhaps it calls a `.find` method if available otherwise it does trivial searching).
In [Linq](http://pfultz2.github.io/Linq/), the find is specialized for mapped containers and for strings(it doesn't check for a `.find` method since that can't be done on msvc). So you can search a `std::vector` like this:
std::vector<int> v = { ... };
auto it = v | linq::find(123);
And you can also search the keys of a map like this: std::map<int, std::string> m = { ... };
auto it = m | linq::find(123);
Plus, it has a contains function, so you can do this: if (v | linq::contains(123))
Or this: if (m | linq::contains(123))
There really is no need for a new operator just for this, since a function will suffice. However, if you really inclined to this, you could always write your own [named operator](https://github.com/klmr/named-operator)(although I don't know if it would become standard): if (123 <in> v)And with that you can build reflection:
#define EMPTY()
#define DEFER(id) id EMPTY()
#define FOREVER() \
? \
DEFER(FOREVER_INDIRECT) () ()
#define FOREVER_INDIRECT() FOREVER
This will print out `?` infinitely. Here is the machinery to evaluate the expression: #define EVAL(...) A(A(A(__VA_ARGS__)))
#define A(...) B(B(B(__VA_ARGS__)))
#define B(...) C(C(C(__VA_ARGS__)))
#define C(...) D(D(D(__VA_ARGS__)))
#define D(...) E(E(E(__VA_ARGS__)))
#define E(...) __VA_ARGS__
EVAL(FOREVER())
Which will expand to something like this: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FOREVER_INDIRECT () ()
Well at the end we see `FOREVER_INDIRECT () ()` which means the algorithm can expand further, so we could just apply more scans: EVAL(EVAL(FOREVER()))
And we get more `?`. And we didn't have to change the expression of the algorithm just the machinery to evaluate it.This is why I say the C preprocessor can act as Turing-complete, because the expression and machinery, while separate, is both in the language itself. This is different than BlooP, which the only possible way to express Turing completeness is through an external source(such as an input file).
Of course, for all practical purposes, the C preprocessor is near Turing-complete enough. The whole goal of the preprocessor is to output a file, we don't need it run indefinitely. We can express almost any useful algorithm, and if it reaches the recursion limit, we just simply apply more scans.