From 2ff21c708cd53d73e2eb2e2958fda8f9e92b169e Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Fri, 24 Nov 2023 18:27:32 +0100 Subject: [PATCH 1/2] fix(algorithms): fix the admonitions in Karel Signed-off-by: Matej Focko --- algorithms/04-recursion/2022-11-29-karel-1.md | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/algorithms/04-recursion/2022-11-29-karel-1.md b/algorithms/04-recursion/2022-11-29-karel-1.md index e30750e..d3cad44 100644 --- a/algorithms/04-recursion/2022-11-29-karel-1.md +++ b/algorithms/04-recursion/2022-11-29-karel-1.md @@ -79,12 +79,15 @@ You can see an example of such map here: As a first step write down any ideas and things that you have noticed or came to your mind. Ideally: -- Write down a nested list of the problems, e.g. +1. Write down a nested list of the problems +2. Write down list of problems that can happen +3. Write down **anything** you consider important to solving the problem - :::info Example +:::tip Example - Problem: I want to find out whether the display on smartphone should rotate. +**Problem**: I want to find out whether the display on smartphone should rotate. +- nested list of problems - Check if display has been rotated - Read data from some sensor - From what sensor @@ -92,30 +95,16 @@ your mind. Ideally: - How do I communicate with the sensor? - What is the meaning of the data that I got? - How can I process it? - - ::: - -- Write down list of problems that can happen, e.g. - - :::info Example continued - - Following the same problem. - +- any problems that can happen - What if the sensor doesn't work? - What if the data doesn't conform to the specification? - What if my formulas are wrong? - - ::: - -- Write down **anything** you consider important to solving the problem, e.g. - - :::info Example continued once again - +- anything important - I could probably use gyroscope. - I should probably look up the datasheet for that module. - I could write some tests to verify that my computations are correct. - ::: +::: ## »Rough« pseudocode @@ -155,7 +144,9 @@ the ZIP-file, you can there: - `skeleton.py` - skeleton for your solution, needs to be put in the same directory as `karel_tk.py` and takes path to the world as a first argument, example usage: - $ python3 skeleton.py stairs.kw + ``` + $ python3 skeleton.py stairs.kw + ``` - of course, this file can be renamed ;) From 311ebacf84286ee272acc2d427e9526e5bbd08fa Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Fri, 24 Nov 2023 18:21:49 +0100 Subject: [PATCH 2/2] feat(cpp): add placeholders Signed-off-by: Matej Focko --- .../2023-11-24-placeholders.md | 205 ++++++++++++++++++ cpp/07-exceptions-and-raii/_category_.yml | 5 + .../placeholders/placeholders.hpp | 77 +++++++ .../exceptions-and-raii/placeholders/test.cpp | 6 + 4 files changed, 293 insertions(+) create mode 100644 cpp/07-exceptions-and-raii/2023-11-24-placeholders.md create mode 100644 cpp/07-exceptions-and-raii/_category_.yml create mode 100644 static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp create mode 100644 static/files/cpp/exceptions-and-raii/placeholders/test.cpp diff --git a/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md b/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md new file mode 100644 index 0000000..a7f4c15 --- /dev/null +++ b/cpp/07-exceptions-and-raii/2023-11-24-placeholders.md @@ -0,0 +1,205 @@ +--- +slug: placeholders +title: Placeholders +description: | + Placeholders that are quite convenient to use when working on the code. +last_update: + date: 2023-11-24 +--- + +Here we will try to implement some placeholders that you can find in other +languages, but I miss them in the C++. I'm taking the inspiration from languages +like Rust (all that we will implement) or Kotlin (`TODO`) that have them +implemented. + +You may ask what placeholders do we need in the code, in our case we will be +talking about TODOs and unexpected situations, such as not implemented branches. + +Namely we will implement + +- `todo`, +- `unimplemented`, and +- `unreachable`. + +## Design + +If we take the two languages mentioned above as examples, there are at least two +ways how to implement them: + +1. _panic_ when they are reached (as they do in Rust), or +2. _raise_ an exception when they are reached (as they do in Kotlin). + +I will choose raising an exception, since the closest equivalent of _panic_ in +C++ would be `assert`s that are (by default) disabled in the _release builds_. + +However I am too lazy to do: + +```cpp +throw todo(); +// or +throw todo("optional note"); +``` + +Therefore we will implement exceptions and also wrap them in functions, so that +we can do: + +```cpp +todo(); +// or +todo("optional note"); +``` + +:::tip + +Wrapping them in a function (or macro) will allow us to do a little magic trick. + +::: + +## Implementation + +We're going to utilize the exceptions, so we'll need to include the `exception` +header and we will start with a simple `_todo` exception class. + +```cpp +#include +#include + +class _todo : public std::exception { + std::string cause; + + public: + _todo() : cause("not yet implemented") {} + _todo(std::string&& excuse) : cause("not yet implemented: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; +``` + +In this case we have 2 constructors: + +1. default constructor without any parameters that will return just + `not yet implemented` +2. and one parametrized with an “excuse” that will return string like: + `not yet implemented: ‹excuse›` + +If we were to use it now, we would need to do something like: + +```cpp +#include "placeholders.hpp" + +int main() { + throw _todo(); + return 0; +} +``` + +## Wrapping in a function + +I am a lazy person, so we will wrap the exception in a function that will throw +it: + +```cpp +void todo() { + throw _todo(); +} +``` + +This can be used like: + +```cpp +#include "placeholders.hpp" + +int main() { + todo(); + return 0; +} +``` + +## Magic trick + +At the beginning I've mentioned that by wrapping the exceptions in a helper +functions that will throw them, we can do a nice magic trick :smile: This trick +will consist of formatted string and for that we will use +[`std::format`](https://en.cppreference.com/w/cpp/utility/format/format) that is +available since C++20. + +We just need to add one more overload for our `todo()`: + +```cpp +#include + +template< class... Args > +void todo(std::format_string fmt, Args&&... args) { + throw _todo(std::format(fmt, args...)); +} +``` + +## Finishing off with 2 more exceptions + +Now we can repeat the same process for the other two exceptions I've mentioned + +- `unimplemented`, and +- `unreachable`. + +In the end we should end up with something like this: + +```cpp +#include +#include +#include + +class _todo : public std::exception { + std::string cause; + + public: + _todo() : cause("not yet implemented") {} + _todo(std::string&& excuse) : cause("not yet implemented: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +void todo() { throw _todo(); } + +template +void todo(std::format_string fmt, Args&&... args) { + throw _todo(std::format(fmt, args...)); +} + +class _unimplemented : public std::exception { + std::string cause; + + public: + _unimplemented() : cause("not implemented") {} + _unimplemented(std::string&& excuse) + : cause("not implemented: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +void unimplemented() { throw _unimplemented(); } + +template +void unimplemented(std::format_string fmt, Args&&... args) { + throw _unimplemented(std::format(fmt, args...)); +} + +class _unreachable : public std::exception { + std::string cause; + + public: + _unreachable() : cause("entered unreachable code") {} + _unreachable(std::string&& excuse) + : cause("entered unreachable code: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +void unreachable() { throw _unreachable(); } + +template +void unreachable(std::format_string fmt, Args&&... args) { + throw _unreachable(std::format(fmt, args...)); +} +``` + +:::info + +Final source code: [`placeholders.hpp`](pathname:///files/cpp/exceptions-and-raii/placeholders/placeholders.hpp) + +::: diff --git a/cpp/07-exceptions-and-raii/_category_.yml b/cpp/07-exceptions-and-raii/_category_.yml new file mode 100644 index 0000000..11206ca --- /dev/null +++ b/cpp/07-exceptions-and-raii/_category_.yml @@ -0,0 +1,5 @@ +label: Exceptions and RAII +link: + type: generated-index + description: | + Materials related to the exceptions or RAII in C++. diff --git a/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp b/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp new file mode 100644 index 0000000..9ffbf8c --- /dev/null +++ b/static/files/cpp/exceptions-and-raii/placeholders/placeholders.hpp @@ -0,0 +1,77 @@ +#include +#include +#include + +class _todo : public std::exception { + std::string cause; + + public: + _todo() : cause("not yet implemented") {} + _todo(std::string&& excuse) : cause("not yet implemented: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +/** + * @brief Indicates unfinished code. + */ +void todo() { throw _todo(); } + +/** + * @brief Indicates unfinished code. + * @param fmt an object that represents the format string + * @param args arguments to be formatted + */ +template +void todo(std::format_string fmt, Args&&... args) { + throw _todo(std::format(fmt, args...)); +} + +class _unimplemented : public std::exception { + std::string cause; + + public: + _unimplemented() : cause("not implemented") {} + _unimplemented(std::string&& excuse) + : cause("not implemented: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +/** + * @brief Indicates unimplemented code by throwing with a message of “not implemented”. + */ +void unimplemented() { throw _unimplemented(); } + +/** + * @brief Indicates unimplemented code by throwing with a message of “not implemented”. + * @param fmt an object that represents the format string + * @param args arguments to be formatted + */ +template +void unimplemented(std::format_string fmt, Args&&... args) { + throw _unimplemented(std::format(fmt, args...)); +} + +class _unreachable : public std::exception { + std::string cause; + + public: + _unreachable() : cause("entered unreachable code") {} + _unreachable(std::string&& excuse) + : cause("entered unreachable code: " + excuse) {} + virtual const char* what() const throw() { return cause.c_str(); } +}; + +/** + * @brief Indicates unreachable code. + */ +void unreachable() { throw _unreachable(); } + +/** + * @brief Indicates unreachable code. + * @param fmt an object that represents the format string + * @param args arguments to be formatted + */ +template +void unreachable(std::format_string fmt, Args&&... args) { + throw _unreachable(std::format(fmt, args...)); +} diff --git a/static/files/cpp/exceptions-and-raii/placeholders/test.cpp b/static/files/cpp/exceptions-and-raii/placeholders/test.cpp new file mode 100644 index 0000000..695d09e --- /dev/null +++ b/static/files/cpp/exceptions-and-raii/placeholders/test.cpp @@ -0,0 +1,6 @@ +#include "placeholders.hpp" + +int main() { + todo("finish later ({})", "in 3 days"); + return 0; +}