Tuesday 29 October 2024

AI for the Rest of Us

 I spoke at AI for the Rest of Us last week. This new 2-day event happened in London, and wanted to help attendees understand what AI is about and how to use it, in plain language. Some talks also considered potential issues, including bias and ethics.  

The mornings had various keynotes, then the afternoon split into 3 tracks, some on Thursday and some on Friday:

  1. Back to Basics: AI Fundamentals
  2. AI in Action: Real World Stories and Lessons Learnt
  3. AI in the Workplace: Productivity Game Changers
  4. Business Strategy Meets AI: Embrace Change and Unlock Opportunity
  5. Developer Experience: How AI is Changing Software Engineering
  6. Responsible AI: Safety, Security, Guardrails and Governance

I was speaking at AI fundamentals, and tried to explain curve fitting, why it's sometimes called regression, and neural networks in under 30 minutes. A challenge, but people talked to me afterwards so I may have succeeded. 

If you don't know why we sometimes use the word regression here's a clue. Francis Galton wrote a paper called "Regression towards Mediocrity in Hereditary stature." Wikipedia has quite a good overview. He observed the heights of children and parents, and spotted they all tended towards a median value. Nothing that profound really, though there is a bias loitering in there. Anyway, the talks were recorded so will be on YouTube at some point. 

I have copious notes, but some highlights were Rachel Lee-Nabors reminding me of Russell and Novig's book, Artificial Intelligence: A Modern Approach. I read that when I started my PhD many years ago. I probably read an older edition but Rachel suggested the 4th edition. It covers a lot of ideas and is a great introduction if you want a good book. Rachel also mentioned Trask's Grokking Deep Learning book. Rachel's title was "AI cram session", explaining lots of details about LLMs and more besides.




Several talks tried to explain LLMs, going into various levels of detail. Ideas from embedding to attention and multilayer perceptrons were covered. These are fundamental parts of LLMs, so no surprise there, for me anyway. 

Of course, there's more to AI than LLMs. I really enjoyed Lisa Becker's talk "Beyond LLM-Washing: When other ML models are simply better". 


She pointed out the potential huge cost of using LLMs and encouraged us to at least consider other methods, like classification or clustering, along with predictive models or anomaly detection. She pointed out using LLMs and GenAI tends to have prestige, but might not be practical. 

I also enjoyed Lianna Potter's talk "Never Neutral: AI Development, Past, Present and Future in Anthropological Research". She describes herself as a digital anthropologist. 


 
She talked through Diana E. Forsythe's book, Studying those who Study Us. The bias that creeps in when people focus on the wrong things never stops! I've not come across this book before, but it's now on a long list of books to read.

Ian Miell's talk about LLMs in the humanities was interesting. He set himself the challenge to get AI to write an essay for him that he had to write at university. He also talked through some AI history, including machines to play chess. The details of his personal project to generate an essay were relatively high level, but easy to follow. 


I also went to Jeff Watkin's talk "Four Horsemen of the Information Apocalypse." He started by asking who invented
  • the light bulb
  • the printing press
  • the internet
These are often wrongly answered. This was a great lead in to talking about misinformation, mal-information, disinformation and non-information. He drew an analogy with a virus spreading and encouraged us to lower the r number, to stop the spread, or at least reduce it. 

I went to several other talks too, but the different afternoon tracks meant I missed many. I look forward to these turning up on the internet. The speakers' brief was to keep things understandable. That's hard if you don't know the audience, but I think the speakers managed. Some technical terms were used, but analogies or simple explanations were offered. 

I'm glad I went. I met new people and had lots of interesting conversations. Having speaker's drinks the night before meant I recognised a few people when I turned up on the first morning, which was lovely. 


Tuesday 24 September 2024

SoCraTesUK 2024

I attended the International Software Craft and Testing Unconference UK just outside Oxford last week for the first time. I have been aware of this for a while but hadn't had the chance to attend before. I had been to another conference which had a single "unconference" track, so I got the idea.

Before the main conference, we had a day of workshops. I ran a 90 minute session introducing C++. That's not much time to learn a language, but I think everyone managed to get something working. I walked though how to build a game of Rock, Paper, Scissors, avoiding any mention of pointers or iterators. You need to be able to handle input, output and generate random numbers, which I believe is a great way to try to learn any language. 

For the unconference, there's no fixed agenda or schedule beforehand. People chat in groups about potential ideas and pitch these in the morning, to see if anyone is interested. If someone wants to go ahead with the idea, they put the title up on a board in a slot for a specific time and place. 

What ended up happening is on their website. I didn't make all the sessions: I needed some headspace and went for a walk round the grounds or did a short gym session a couple of times. 

The first session I went to was about confidence. Harram proposed this. She hadn't been to this unconference before (nor had I), so she's braver than me. It seems an old manager told her she wasn't confident enough, so we unpacked what that might mean. I personally didn't feel it was useful or helpful feedback. It's all too easy to be confident but wrong. 

After that I went for a short wander and then attended the end of "Workplace conflict, what can ancient warrior arts of the mystic East teach us?" 


I've done some martial arts before, but wasn't familiar with the specific ones mentioned here. However, the idea of stepping to the side rather than pushing back cropped up and makes sense. I missed the beginning, so I only caught some of this. Thinking about what "stepping sideways" might mean in a discussion was useful. 

Next I went to "As freelancers, how do we decide what to spend our time on", run by Clare.  



I have been available for short consultancy this year, but have spent far too much time preparing content for things that got cancelled or getting distracted. To be fair, I have also had a book published and started another one, so I have managed to do some things. Saying "No" once in a while is a good idea. This made me think about how to make better choices next year. 

I then went to "What I wish I had known about retirement before I retired", which ended up being a bit focused on money and cashflows, simply because that's what people were asking. I shall take stock and see how I'm doing. Things seem to be getting harder for people. For example, I don't have a student loan, but many younger people do, and that makes planning more difficult. 

On Saturday I went to Seb's "BDD reboot". I have had a session about BDD accepted for OOP next year, and planned to talk about my experiences. Seb's session was a useful reminder of what BDD is really about - clue the middle D for "driven" is important. It's certainly not about slapping Given-When-Then in your tests. Many of the rooms were named after flowers, and this was, appropriately, in Rose. 



Next, I went to "Challenges when dealing with time-dependent & historical data". I had hoped someone would give me all the answers, but we just chatted through things we have had to deal with and what we tried. My examples involved reference data changing and how to maybe label versions so you get the same outputs for regression testing. Dealing with time dependent data is hard. 

There was a discussion over lunch based around "Unionizing in Tech".  Listening to the ins and outs of trying to be a union member in a large tech company was hard. I mentioned a book I read a while ago: Reorganise: 15 stories of workers fighting back in a digital age, which is about other ways people band together to support each other. 

I couldn't settle my head after that so I flitted between sessions then went for a walk. I then went to "I need 28 thoughtful / gratitude reflection style questions".  We sketched out questions that could be used in an app which checks in with you each day and shares your answers with others, maybe inspiring them too. Why 28?  So the questions could cycle around every four weeks. I'm not sure how useful we were, but things like "What have you learnt recently?" "What would you like to learn next?" etc... ended up on the list. 

The last session I went to that afternoon was Clare with "Recently diagnosed or undiagnosed autistic - ask me anything". Most people who attended were either diagnosed autistic or suspect they are. One or two were there because they have an autistic child. I suspect I might be autistic, and I wondered what difference the diagnosis had made to Clare. I nearly ended up in tears a few times, for reasons. The big thing I realised in this session was how many women were at the conference, especially compared to conferences I usually go to. 

In the evening, there were some Lightning talks, where people volunteer a short talk, for a maximum of five minutes, on the spot. All kinds of things were covered. Clare gave the last talk about how a hot air balloon ride is like an unconference. I didn't make notes, so I no longer remember who else said what. But that's OK. Lightning talks are a great way to allow people to do a little, which is less scary than a whole session.

Finally, Mervi gave an LED hula hoop performance. You had to be there.



Monday 5 August 2024

Why I wrote Learn C++ by Example

I recently shared some details about my latest book "Learn C++ by Example".


You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG

There are a lot of C++ books, so why did I write another one? Well, many books delve into the details of a specific language version. As you may know, C++ remained relatively stable until C++11. This felt like a new language in many ways. Some things became easier, for example using a range based for loop meant you can show the contents of a container without needing to learn about iterators first:

#include <iostream>
#include <vector>

int main()
{
    std::vector numbers{1, 3, 5};
    for(auto number : numbers)
    {
        std::cout << number << '\n';
    }
}

Since C++11, there has been a new standard every three years. In fact, the code listing above is now old, because we can use std::println instead of std::cout and import modules rather than include headers. My book didn't cover all the newer features, because I wanted to give just enough to help people get back up to speed. 

My previous blog posts did show what I covered. The chapters have the following titles:

1 Hello again, C++!
2 Containers, iterators, and ranges
3 Input of strings and numbers
4 Time points, duration, and literals
5 Creating and using objects and arrays
6 Smart pointers and polymorphism
7 Associative containers and files
8 Unordered maps and coroutines
9 Parameter packs and std::visit

As I said, this doesn't cover everything. However, I think it gives just enough to help you get back up to speed if you used to know at least some C++, but haven't used the language for a while.

I have been using C++ since the 1990s, along with various other languages. I used to work in finance in London. Trying to get a position can be a challenge. Many organisations give you a thorough grilling, with a homework challenge, possibly a multiple choice "quiz"  and one or more face to face interviews. Aside from implementing linked lists on whiteboards, or spotting missing semicolons on paper printouts, you often get asked about dusty corners of the language, so many people practice and learn a huge number of details about C++. 

I did learn some Python and C# too, which meant I had to take time to revise if I wanted a contract using C++ again. Watching the language change and move would a bit overwhelming, but since I edit ACCU's Overload magazine, I was aware of some newer features I should probably catch up with. Before writing the book I found time to practice some modern C++, and started to form a list of things I knew and things I wanted to learn.

Meanwhile, I sometimes review manuscripts for Manning, and have been a technical proofer for some of their books. I noticed I hadn't seen a C++ book from them for a while. I have a copy of Anthony Williams' C++ Concurrency in Action and recently reviewed a couple of C books. I suggested the need for a short C++ book covering significant changes since C++11 and my proposal was accepted. 

People who have read my book have told me how useful it's been. If you used to know C++, and feel sad because you haven't managed to keep up, don't give up. Find one or two small things and learn those. You might never catch up with all the changes, and C++ will keep evolving. However, you can practice a little once in a while to stop yourself from going completely rusty.




Monday 15 July 2024

C++ On Sea trip report

 

I went to C++ On Sea again this year, attending the main conference. I spoke about Swarm Optimisation algorithms. I wrote a brief blog post about these a while ago, if you want a quick overview. I also hosted the lightning talks.



On the first evening, we had six speakers and a last minute bonus from Jon Kalb:
  1. Jan Wilmans, A Magical chat about C++ with GPT3+
  2. Anders Schau Knatten, C++ Quiz
  3. Cassio Neri, My favourite UB - Part II Russell's Paradox in C++
  4. Sanket Singh, Unlocking the Power of Advanced C++ Compiler Flags: Boost Performance and Debugging Efficiency
  5. Amir Kirsh, delete [ ]
  6. Mark Williamson, Undoom - reviving a zombie with a time travel debugger
  7. Jon Kalb, Wisdom in Keywords
I was speaking directly beforehand, which was a challenge. People sign up and send me slides (unless they are doing a demo on their laptop), so I couldn't poll emails while I was talking. I had prepared a game of "Coding rockstars" beforehand - or at least had some pictures and ideas.  For example, a picture of Taylor Swift. See what I did there?

On Thursday, (almost) immediately before the speakers' dinner, we had another session of lightning talks, with more speakers this time:
  1. Andrew Drakeford, Variadic Reduction 
  2. Sandor Dargo, Do engineering teams really resemble sports teams?
  3. Roth Michaels, Spelling and Pronunciation in C++
  4. Daniel Jump, Replacing legacy string type
  5. Koen Poppe, Implicit conversion, friend or foe 
  6. Kris Jusiak, Static assert is almost all you need! 
  7. Alex Merry, Slide Core Guidelines
  8. Phil Nash, All the Defaults Are Backwards : Let's Fix That
  9. Ambrus Tóth, HyloDoc: Documentation Compiler for Hylo
Dave Abrahams gave the opening keynote about Hylo, one of many languages investigating safety in C++ and potential improvements. The focus was on value semantics, which he described as the "absence of entanglement".  Dave mentioned https://www.bemanproject.org/  My hand scribbled notes don't have any context, but their website says their aim is to "support the efficient design and adoption of the highest quality C++ Standard libraries."

Princess Bride quote: "That word you keep using, ..." in answer to the question "What does a reference mean?"

Next up, for me, was Jason Turner talking about constexpr. He started simple, and gradually added more details. I will need to relisten to this, because I know he covered a few edge cases I hadn't thought of, like lambda captures. I have noted constexpr doesn't change the lifetime of an object. On the face of it, that's obvious, but it's too easy to think it's some value baked in at compile time.

Next I listened to (some of) Björn Fahller's talk on cache friendly data structures. I was busy piecing together lighting talks, so hid up on the balcony to avoid being disruptive. He was talking through a  data structure with good locality of reference and showed efficient filters and deletes, and I did note down his github link. This says "Elements are kept packed towards the beginning of each column, but can be referenced using stable row_id type." This means tracking what has been deleted. One of many cases where a relatively easy to state problem leads to lots of thinking.

I spoke next, giving a high level overview of many nature inspired "swarm" algorithms, and then went into depth on the Cat Swarm algorithm.  You're right, cats don't swarm, but each swarm algo has agents with a position and velocity. The position is a potential numeric solution to a problem, and the velocity gives agents a trajectory, which changes over time, moving towards better places, for some definition of better. In our case, up mean the cat would be let out of a paper bag, so higher coordinates were more likely. 

After the lightning talks, I wanted to collapse in a heap. A small gang of us went to a Turkish restaurant just down the road, which serves a mix of vegetarian friendly and meaty food, in huge portions. Five stars.  

Thursday was less intense, which allowed me to concentrate on Cassio Neri's dragon talk. The full title was A new dragon in the den: fast conversion from floating-point numbers. Another easy to describe problem - print a numeric value. But how many digits, and how quick can you make it? He introduced a new algorithm called Teju Jagua which is a mythological monster: Cassio took great delight in telling us the tale. He's a great story teller. I'll have to go back slowly through the clever maths he did, but meanwhile here's a picture of the seven headed monster:




Next, I went to Jonathan Müller's talk An (In-)Complete Guide to C++ Object Lifetimes. There were so many C++ features I've either never used, like std::launder, or never heard of like std::destroy_at or std::start_lifetime_as. It's always good to discover new language features but my brain was melting by the end of this talk.

I went to see next, talking about Elevating Precision in C++: A journey below the surface of floating-point. Two floating point talks in one day might seem a bit much, but I've not heard him speak before,  and he asked me to sign a copy of my Learn C++ by Example book earlier, so I went to his talk. He talked about Dekker doubles, which led to an obligatory joke about double decker (buses). He asked if anyone knew what a bfloat was, and I made a fool of myself guessing the 'b' stood for binary - clearly not, on reflection. It's a brain float (bfloat16),   It's used for serious numerical computing, including neural networks, hence the name. Wikipedia tells me

It preserves the approximate dynamic range of 32-bit floating-point numbers by retaining 8 exponent bits, but supports only an 8-bit precision rather than the 24-bit significand of the binary32 format.
Daniela Engert then gave her keynote, called Not getting lost in translations. She was talking about Unicode, and how much you can do at compile time. Of course, constexpr got a mention again. I listened, while being mildly distracted by lightning talk emails, but made no notes. I know she showed some really interesting approaches, but I'll have to listen to the recording. It's nice to just listen and let your brain wander once in a while. 

We then had more lightning talks, being less ambitious for the in-between parts. I wasn't sure what to go for after coding rockstars, so I just asked "What's next?" For example,

1, 2, 3, ?

Yep. 4. Start simple. We went downhill from there though. 

I started Friday with Roth Michaels' How and when to write a template. This was part of the C++ fundamentals track labelled as for beginners. Again, we started simple. For example std::string is a template. Roth then considered various types of templates:
  1. class
  2. function
  3. alias
  4. variable
  5. lambda
As you might imagine, things got complicated, and Roth somehow covered EVERYTHING. I knew almost all the ideas he covered, such as std::visit, template template parameters and a question sparked a brief discussion about splitting templates into two header files, including an impl.h, to avoid all the things in one place. I'd forgotten about doing that. 

Next, I went to see Tristan Brindle talking about Practical Tips for Safer C++. This was also in the C++ fundamentals track, this time aimed at beginner or intermediary level. He talked about trapping or wrapping integer overflow, again starting with some simple slides, asking if code was potentially unsafe. Simple things, like sorting numbers can lead to trouble if your container has NaNs. So he suggested using std::is_lt for sorting. He mentioned his Flux library once or twice - it's worth looking at. One point he made, which cropped up several times at the conference, is constexpr can find UB.

I went to Peter Muldoon's talk, Dependency Injection in C++ : A Practical Guide after lunch. He considered various ways of injecting code
  1. link time
  2. virtual functions and inheritance
  3. templates including concepts
  4. type erasure
  5. null objects or stubs
He rejected the first approach quickly. It gets out of hand too easily. He then showed examples of the other approaches, which were all useful. The essence of his talk was approaches to take to make code testable. 

This led on nicely to the next talk by Steve Love, called Testable by Design. Steve built up an example of a thermostat and heating controller. Again, this started simple, and he showed various ways to chain together code, so the heating would go on or off at various times of day, without using the system time directly. If you do that, you are in danger of having a test that only passes at certain times of day. 

Finally, Klaus Iglberger gave the closing keynote, There is no Silver Bullet. He also talked about design choices, contrasting full on inheritance with templates and finally value-based OO, using type erasure and impls. He mentioned Ivan Čukić's Prog C++ talk, which was the closing keynote at MeetingCpp in 2023. He also contrasted the performance of each approach, but made us promise not to take the numbers too seriously. People can get hung up on performance, but extensibility is important too. The value based OO wasn't as quick as template tricks, but did make it easier to extend the internals or externals more simply.



It was a great conference, and I met new people as well as catching up with friends. Thanks to everyone who was brave enough to give a lightning talk, ask a question in a talk, or willing to attempt to answer a question from a speaker, even if they got it wrong. 


Monday 8 July 2024

Learn C++ by Example: Chapter 9

I have been sharing some details about my latest book "Learn C++ by Example", and gave an overview of chapter 8 last time. There are 9 chapters, so this is the final blog about the book's contents.




You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG

The final chapter explains parameter packs and uses the std::visit pattern. Since we're on the last chapter, we also get opportunities to practice variants, std::format and ranges. We used a std::variant back in chapter 5, to hold either a Card or a Joker. Chapter 5 noted a variant's definition:

template <class... Types>
class variant;

We learnt that the dots are called a parameter pack, allowing us to use zero or more template arguments. We used a variant with two types, a Card or a Joker, back then, but we could have more than two types. We used std::holds_alternative<Joker> to detect if a card was actually a Joker. With more than a couple of types, this can get clumsy, so this final chapter shows another approach.

We explore how to write variadic templates, i.e. templates with at least one parameter pack, looking at fold expressions. Jonathan Müller's blog has some great examples if you want more details. The three dots in the template head indicate a parameter pack,  and we use three further dots to unpack the parameters, for example

template<typename... Ts>
auto add(const Ts&... tail)
{
    return (... + tail);
}

allows us to call add(1, 2) or add(1, 2, 3). You need to watch out for left or right association, for some operators. 

The mini-project in this chapter is building a slot machine. We build up three "reels" (vectors) of numbers, rather than more traditional fruits or similar for slot machines. In fact, we use the triangle numbers. If you can't remember what they are, read my book or find a good online resource.  Just think of arranging snooker balls in a triangle and counting how many you have: 1, 3, 6, 10, 15, 21, ...

If you consider the last digit of each triangle number, a pattern emerges, and repeats. The last digit will be 0, 1, 3, 5, 6 or 8 and nothing else. 8s and 3s are less likely than the others. If we set up three reels with these numbers and compare the final digits we can give a payout, as a slot machine would. Two matches gets a small payout, and all three gets more. In fact, we give a higher payout for 8s and 3s since they are less likely. Trying to calculate a fair payout was a challenge, so I spared the readers and used an approximation. 

The first game just lets the reels spin. How do we spin the reels? We shuffle the vectors first, so we don't know what's going to happen initially, but after that the reels want to move forward by a random amount. And yes, "That's a rotate".  (Ólafur Waage's blog "Everything is a rotate" will explain that meme if you've not heard it before).

Because the reels stay in order, we can display the previous and next numbers above and below the current line, and allow a hold or nudge something like a real slot machine. By adding three structs, 

#include <variant>
struct Hold {};
struct Nudge {};
struct Spin {};
using options = std::variant<Hold, Nudge, Spin>;

we can extend the game relatively easily.  One approach is using a struct with an overloaded method for each type:

struct RollMethod
{
    void operator()(Hold)
    void operator()(Nudge)
    void operator()(Spin)
};

This is far better than checking std::holds_alternative, for each type. The chapter goes on to explain the Overload pattern and how to use std::visit. We need a different function for each type, or double dispatch. Have an experiment, and see if you can code this up.

The chapter also briefly mentions C++17's execution policies, mutable lambdas and std::views::zip, as well as giving extra practice with algorithms and std::format

So, some questions for you
  1. Can you find the repeating pattern of the final digits of the triangle numbers? (Write code to generate them, and have a look).
  2. Can you rotate a vector by a random amount? (It seems a few people can't remember how to use std::rotate, so practice).
  3. Can you use std::visit for the three different options, hold, nudge or spin? 
I've now shared an overview of each chapter. Have a play around with the mini-projects and get in touch if you can think of other good learning examples. 

 


 

 



Monday 1 July 2024

Learn C++ by Example: Chapter 8

I have been sharing some details about my latest book "Learn C++ by Example", and gave an overview of chapter 7 last time. There are 9 chapters, so this is the penultimate blog about the book contents.




You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG

Chapter 8 is predominantly about unordered maps and coroutines. The previous chapter used std::map, which has been in C++ for a long time but allowed us to learn several new features anyway. This chapter uses an std::unordered_map for contrast. The unordered containers were introduced in C++11. They use hashes to place elements in buckets, so the std::unordered_map is a hash map. There are many overloads of std::hash but you might need to write one to use the hash map, for example for your own class or std::tuple.

The mini-project in this chapter is a game of matching pennies. Two players secretly pick heads or tails on a coin, and simultaneously show their choice. One player is trying to get a match, and the other tries to avoid this. It's not hard to write code where the computer wins on a match, using random numbers for the computer's turn, giving a basic version of the game. 

Now, Claude E. Shannon wrote a short paper in 1953 called “A Mind-Reading (?) Machine” Yes, that Claude Elwood Shannon - the accomplished unicyclist and founder of information theory. The paper has a question mark in the title because the machine isn't really mind-reading. Shannon tracked whether the penultimate outcome was a win or lose, and if the player then changed from heads to tails (or vice versa) or played the same move and thereby won or lost. The three elements can form a lookup table and we can record whether the next choice was a change or not. If we just store the last two values  (change or not) for a given state, we can perform a lookup and if they match, make a prediction. If they don't match, the computer plays at random. The mind-reading machine is surprisingly effective, though you can outsmart it if you track the same state yourself. 

Coding it up gives the opportunity to practice all kinds of C++ features, as well as think about how to form a hash for the three part key. The first part of the chapter creates a MindReader class template, taking a generator and distribution as template parameters, making the code using randomness easy to test. Armed with a mind reader, we then see how to use this in a coroutine. Doing so makes no difference to the matching pennies game, but is an opportunity to learn about this new, much discussed feature of C++.  

You can pause a coroutine, say after yielding a result, and resume later. CppReference says 
This allows for sequential code that executes asynchronously (e.g. to handle non-blocking I/O without explicit callbacks), and also supports algorithms on lazy-computed infinite sequences and other uses.
Coroutines allow cooperative multitasking for example running some code, then suspending while awaiting a result. You need to write a lot of boilerplate to get a coroutine working, but the compiler will help you remember what to add. Again, the compiler will point out anything you need if you forget something. 

If you see a function with one of the following 
  • co_await
  • co_yield
  • co_return
the function is a coroutine. The return type must then fill in the boilerplate, including how to start and stop, and what to do with a co_await, co_yield or co_return

Ivan Cukic gave a keynote at MeetingCpp in 2023. He mentioned coroutines (and lots of other ways to style C++ code for various use cases and neatness). Go look at the slides: From slide 69, he talks about "C++ error handling, let’s abuse the co_await operator." An usual use of coroutines, but interesting.

So, some questions for you:
  1. Why are the C++11 containers called unordered?
  2. How would you write a hash function for a std::tuple, say of just three elements?
  3. Can you list all the parts a coroutine's return type needs?

Monday 24 June 2024

Learn C++ by Example: Chapter 7

I have been sharing some details about my latest book "Learn C++ by Example", and gave an overview of chapter 6 last time.



You can buy my book directly here: http://mng.bz/AdAQ - or just go look at the table of contents. You can also buy it from Amazon: https://amzn.to/4dMJ0aG 

Chapter 7 is mainly about std::map and has a short section on loading a file. We build a game of "answer smash" which gives two clues to words that contain common letters at the start of one and end of the other. This means they can be overlapped. For example, a vector is a “sequential container supporting dynamic resizing,” and a torch could be defined as a “lit stick carried in one’s hand,” so smashing together the words vector and torch
[vector]  [torch] ->  [vec][tor][ch] -> vectorch
gives the answer vectorch.

Now, as you  probably know, std::map has been in C++ for a long time. In fact, C++11 introduced an unordered map, so why spend a chapter looking back rather than forwards? A reminder about some basics, like what the operator[] does (hint - it's not const and might do two things) are useful, and we'll explore a std::unordered_map in the next chapter. 

Using a map still helps us learn some new features. Many operations use a std::pair<const Key, T>, which can mean your code has 
it->first 
or 
it->second 
dotted around. Since C++17, we can use structured bindings to bind such pairs directly using more helpful names, for example:
for (const auto & [key, value] : dictionary)

We can bind to std::tuple and more besides. We can bind to arrays and even a structure’s non-static members too. For example, given

struct DataObject { int x{ 0 }; double y{ 1.23 }; };

we can write

DataObject data {};

auto [x, y] = data;

The chapter briefly looks at std::string_view, as a potentially more efficient way to concatenate strings. You need to be careful with lifetimes if you use this though. CppReference says 
It is the programmer's responsibility to ensure that std::string_view does not outlive the pointed-to character array


The chapter also includes a brief overview of big-O (order) notation, to help us think through potential inefficiencies, and this helps as a basis for unordered (hash based) lookup table in the next chapter. 

We also use a std::multimap, to allow duplicate values per key.  This allows us to load a dictionary from a file. There are several free dictionaries on the internet. Take your pick, but be warned my book only handles ASCII - other character sets would need a whole book, or at least a dedicated chapter or two! Loading a file doesn't need much work, once you've got the hang of streams. An input file stream is called std::ifstream, We can open a file, using its name, which may need to be fully pathed:

std::ifstream infile{ filename };

and use the stream in a Boolean context to see whether it is open:

if (infile)

// all good

The stream closes as it goes out of scope, which is sensible. 

To make a proper game, we need some randomness, so use std::sample to sample a few words. The challenging part is picking overlapping words.

So, some questions for you
  1. If we use operator[] for a std::map, say dictionary["word"], what are the two things that might happen?
  2. Can you remember how to find all the values for a given key in a std::multimap? (Clue: look up lower and upper bound)
  3. Have a go at finding words that can overlap a given word. (Maybe find a free dictionary so you can look up the words, and pick one at random to start with).