Paul Fultz II
If you find the chaining much cleaner, then perhaps you could make it a pipable function instead:
int_<10> | times([]{ std::cout << "foo" << std::endl; });
This way it could still apply to any IntegralConstant. « []
That's an interesting idea. However, Hana does not have a concept of pipable function, so that would need to be added somehow.
Well, if you use Fit in the future, then Fit already provides the mechanism for that.
Sure, but a proper library-based Optional allows one to represent failures caused by more than invalid expressions, which I think is more generally useful. For example, you can define a safe division that returns `nothing` when you divide by zero. Using SFINAE for this seems like using a hammer to screw something. Also, Optional allows more sophisticated operations like
transform(opt, f) -> applies f to the optional value if it is there, and return just(the result) or nothing. filter(opt, pred) -> keep the optional value if it is there and it satisfies the predicate
and many more. Composing optional values like this using SFINAE might be harder, IDK.
I don't see why it would be hard. Plus, there is a compile-time performance benefit, since the compiler will stop at the first substitution failure.
I don't know, I just couldn't think of a way to easily implement something like the compile-time calculator at [1] using raw SFINAE. I think it is easier to wrap SFINAE behind an object and to use actual functions to manipulate this object rather than operating at the SFINAE-level directly, even though this surely gives a compile-time benefit. I'm not saying it's impossible, I'm just saying it needs a lot more creativity than using an Optional object, especially since C++ programmers will be familiar with the runtime concept when std::optional gets in.
Awesome. Have you thought about using a different documentation tool instead, like mkdocs or sphinx?
« []
Yes, I'm currently considering switching away from Doxygen. Though I don't know what I'd switch to. I have almost only one requirement; that the documentation be written in the source code.
Well I use mkdocs for Fit, and I write my documentation in the source code, but I have a script that slurps them up. Perhaps, mkdocs could be extended to do this automatically.
I looked at your setup and I find it quite nice. However, I'm worried about a couple of features I need. For example, it is possible to include code snippets taken from actual files for the examples? Also, is there some cross-referencing going on in the source code, so links are generated automatically? Overall, I think the idea of using a template to generate a static site like they do is the best idea and it's the future, but I'm just worried the project might not provide enough features at the moment?
Well, there is several ways it could be formailised, but either `head` and `tail` do not exist for an empty sequence,
I don't want to use SFINAE to determine this. What if we want to support runtime Iterables like std::vector, that only know they're empty at runtime?
Then `is_empty` would be required for runtime sequences.
or if `tail` always returns an empty sequence even when empty, you just detect that `seq == tail(seq)`.
Well, `tail` will fail when called on an empty sequence. But let's assume this was not the case. You would then be required to implement `==` for your Iterable, which is much more complicated than implementing `is_empty`.
Well you could simply rely on `std::is_same`. At least, this only applies to compile-time sequences, not runtime sequences.
make_tuple(int_<1>) compares equal to make_tuple(long_<1>), even though they have different types. So std::is_same wouldn't be general enough. Overall, I think asking for is_empty to be specified explicitly is very natural, and it should also be very easy to do. Say you're writing a lazy stream or some other sequence generating stuff on the fly. At the most basic level, there are three things you need to provide to your users: - A way to get the first element of the stream, i.e. the current element. That's the `head` function. - A way to advance the stream by one position, i.e. to get to the next element. That's the `tail` function. - A way to know when the stream is done producing values. That's the `is_empty` function.
1. Concatenating ranges does not make sense. A Hana Range is a contiguous sequence of compile-time integers. What happens when you concatenate `make_range(0_c, 3_c)` with `make_range(6_c, 10_c)`? It's not contiguous anymore, so it's not a Range anymore.
Even though concat takes a Range, why can't it just return a tuple instead? « []
`concat`'s signature is
M(T) x M(T) -> M(T)
where M is any MonadPlus. Mathematically, this is similar to the operation of a Monoid, except it is universally quantified on T. It would really break the conceptual integrity
How does it break the conceptual integrity? Isn't a Tuple a MonadPlus as well?
The M has to be a single thing. It can't be a Range and a Tuple at the same time. In other words, Range(T) x Range(T) -> Tuple(T) does not match the signature M(T) x M(T) -> M(T) but it does match A(T) x A(T) -> M(T)
How is it less usable? It seems like it would be more usable, since the library can now support compilers with no or flaky variable templates. « []
I simply mean that `int_<1>{}` is less pretty than `int_<1>`. It is longer by about 28% and most importantly it defeats the philosophy that we're manipulating objects, not types.
I don't see how it breaks the philosophy. `type<T>()` is obviously an object, and it looks even more so like an object than a variable template. It is only two more characters, and is simpler and cleaner than using the variable templates.
I really don't think it's cleaner, but that's subjective.
At any rate, compilers other than Clang and GCC are probably missing far too many features (other than variable templates) for them to compile Hana. I don't think variable templates would change much to that.
Well, it might be possible to support compilers such as gcc 4.9 or clang 3.4. Obviously, visual studio will be out of the question for at least another half of decade.
I have no interest in supporting non-C++14 compilers. Hana is a cutting edge library, and much of its purpose would be lost if it were to include workarounds for older compilers. We're in 2015, and compilers will catch up. Also, Hana proposes a new paradigm. We don't know how to fully take advantage of it, and we don't know what are its limits yet. A lot of time will pass before it replaces Fusion and MPL, and it might also never happen. I still think Hana will stay an "experimental" library used mostly by hardcore C++ programmers for at least a couple of months. These programmers are not stuck on Clang 3.4 anyway, so supporting it adds little value IMHO. Finally, there are usages of generic lambdas and generalized constexpr that would most likely make older compilers scream. I don't think variable templates are the biggest anti-portability factor in Hana.
Using Apple's clang 6, which corresponds to clang 3.5 off of the trunk. « []
So you're with XCode < 3.6, right? This is not supported, unfortunately. I don't know when Apple branched of clang 3.5, or what they did to it, but it happily explodes on my computer too.
Well its Xcode 6.2.
Sorry, I meant to ask if you were using Xcode < 6.3 (not 3.6), which you are. As documented in the README [2], it is unfortunately unsupported. However, you're on OS X and you have Homebrew (I __know__ you do :-). brew tap homebrew/versions brew install llvm36 It's very quick to install because it's a bottle, so you don't have to compile it yourself. And then Hana will be fully working. Regards, Louis [1]: https://goo.gl/pm6fKb [2]: https://github.com/ldionne/hana#prerequisites-and-installation