Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Two silly problems

52 views
Skip to first unread message

Alf P. Steinbach

unread,
Dec 26, 2019, 10:47:45 AM12/26/19
to
Why, with the below code, do I get this result:

> echo no no no not ever | a
ever 1
no 1
not 1

I had expected a count of three for "no".

Also, how the feck does the commented line cause a Most Vexing Parse? I
was sure that by having a constructor call with `cin` as argument there,
i.e. a value argument, there could be no vexing parse. But g++ just
doesn't like it and then misleadingly complains about something later in
the code, using an avalanche of idiot diagnostics so as to ensure one
would waste time on it.


-------------------------------------------------
// Read a file of text, determine the n most frequently used words, and
print out a sorted
// list of those words along with their frequencies.
//
//
https://medium.com/@vgasparyan1995/a-little-bit-of-code-c-20-ranges-c6a6f7eae401

// Assuming
// * ASCII lowercase text
// * No punctuation.

#include <iterator>
#include <iostream>
#include <string>
#include <unordered_set>

template< class Key > using Multiset_ = std::unordered_set<Key>;

auto main()
-> int
{
using std::cin, std::cout, std::endl, std::string;
using Iit = std::istream_iterator<string>;
const Iit end = Iit();
Multiset_<string> words( Iit( cin ), (Iit()) ); // OK
//Multiset_<string> words( Iit( cin ), Iit() ); //! Most
vexing parse?
for( const string& s: words ) {
cout << s << ' ' << words.count( s ) << endl;
}
}
-------------------------------------------------


- Alf (possibly in superstupido-mode, for various reasons)

Alf P. Steinbach

unread,
Dec 26, 2019, 10:51:58 AM12/26/19
to
On 26.12.2019 16:47, Alf P. Steinbach wrote:
> Why, with the below code, do I get this result:
>
> > echo no no no not ever | a
> ever 1
> no 1
> not 1
>
> I had expected a count of three for "no".

Oh, just a typo. I had forgot to writ "multi" in std::unordered_multiset.


> Also, how the feck does the commented line cause a Most Vexing Parse? I
> was sure that by having a constructor call with `cin` as argument there,
> i.e. a value argument, there could be no vexing parse. But g++ just
> doesn't like it and then misleadingly complains about something later in
> the code, using an avalanche of idiot diagnostics so as to ensure one
> would waste time on it.

But this? I can't get my head around it. Right now.

Bo Persson

unread,
Dec 26, 2019, 10:56:01 AM12/26/19
to
Some more coffee needed, possibly?

Multiset_ sounds like a multiset, but it really is not if we read the
using-line carefully. :-)

And for the most vexing parse - cin is a value, but it *could* also be
the name of a parameter for a (hypothetical) words function. So parsing
a declaration wins!


Bo Persson



Alf P. Steinbach

unread,
Dec 26, 2019, 11:07:29 PM12/26/19
to
Thanks.

I wanted to see how conventional C++17 code fares against the C++20
Range-based pipeline stuff in the linked to article

https://medium.com/@vgasparyan1995/a-little-bit-of-code-c-20-ranges-c6a6f7eae401

So the code below is what I came up with. It relies on two of my own
libraries for some small stuff that avoids a details mess.

To me this conventional code is easier to read and to reason about than
the Ranges code, but to the author of that article it's evidently
opposite. I suspect that most of those who love Ranges are of a
mathematical inclination, and that it reminds them of functional
programming. Maybe.


--------------------------------------------------------

// Read a file of text, determine the n most frequently used words, and
print out a sorted
// list of those words along with their frequencies.
//
//
https://medium.com/@vgasparyan1995/a-little-bit-of-code-c-20-ranges-c6a6f7eae401

// Assuming
// * ASCII text.

#include <cppx-core-language/all.hpp> //
https://github.com/alf-p-steinbach/cppx-core-language
#include <cpp/all.hpp> //
https://github.com/alf-p-steinbach/Cpp-Header-Collections

namespace app {
$use_std( cin, cout, endl, quoted, string, string_view, vector, min );
template< class Key, class Value > using Map_ =
std::unordered_map<Key, Value>;

$use_cppx( Truth, Size, Index, hopefully, fail, span_of, string_to_ );
namespace ascii = cppx::ascii;
using namespace cppx::syntax; // String assembly via
"<<".

auto sans_punctuation( const string_view& s )
-> string
{
string result;
for( const char ch: s ) {
if( not ascii::is_punctuation( ch ) ) {
result += ch;
}
}
return result;
}

auto words_and_counts()
-> auto
{
Map_<string, Size> result;
using In_it = std::istream_iterator<string>;
for( const string& s: span_of( In_it( cin ), In_it() ) ) {
const string word = ascii::to_lowercase( sans_punctuation(
s ) );
if( word.length() != 0 ) {
++result[word];
}
}
return result;
}

struct Word_info { string text; Size count; };

auto order_by_decreasing_counts( const Word_info& a, const
Word_info& b )
-> Truth
{ return a.count > b.count; }

void run( const vector<string_view>& command_parts )
{
hopefully( command_parts.size() == 2 )
or fail( "Usage: "s << command_parts[0] << " N_ITEMS" );

const Size n = string_to_<Size>( command_parts[1] );
vector<Word_info> sorted;
for( const auto& pair: words_and_counts() ) {
sorted.push_back( {pair.first, pair.second} );
}
sort( $items_of( sorted ), order_by_decreasing_counts );
$repeat_times( min<Size>( n, sorted.size() ) ) {
cout << _i + 1 << ": "
<< quoted( sorted[_i].text ) << ' ' <<
sorted[_i].count << " time(s)"
<< endl;
}
}
} // namespace app

auto main( int n_args, char** args )
-> int
{
$use_std( vector, string_view, exception, cerr, endl );
try {
app::run( vector<string_view>( args, args + n_args ) );
return EXIT_SUCCESS;
} catch( const exception& x ) {
cerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
--------------------------------------------------------

- Alf


Mr Flibble

unread,
Dec 27, 2019, 11:38:41 AM12/27/19
to
On 27/12/2019 04:07, Alf P. Steinbach wrote:

>     $use_std( cin, cout, endl, quoted, string, string_view, vector, min );

Egregious (std:: preferred).

>     template< class Key, class Value > using Map_ =
> std::unordered_map<Key, Value>;

Egregious (adds nothing but obfuscation).

>     $use_cppx( Truth, Size, Index, hopefully, fail, span_of, string_to_ );

Egregious (std:: preferred).

>         hopefully( command_parts.size() == 2 )
>             or fail( "Usage: "s << command_parts[0] << " N_ITEMS" );

Egregious (adds nothing but obfuscation).

>         $repeat_times( min<Size>( n, sorted.size() ) ) {

Egregious (adds nothing but obfuscation).

> auto main( int n_args, char** args )
>     -> int

Egregious (delibarate troll or OCD).

>     $use_std( vector, string_view, exception, cerr, endl );

Egregious (std:: preferred).

> - Alf

/Flibble

--
“You won’t burn in hell. But be nice anyway.” – Ricky Gervais
“I see Atheists are fighting and killing each other again, over who
doesn’t believe in any God the most. Oh, no..wait.. that never happens.”
– Ricky Gervais
"Suppose it's all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates
a world that is so full of injustice and pain. That's what I would say."

Alf P. Steinbach

unread,
Dec 27, 2019, 2:05:57 PM12/27/19
to
On 27.12.2019 17:38, Mr Flibble wrote:
>
> Egregious (std:: preferred).

Why do you prefer to repeat a bit of text ad nauseam? It's more to
write, more to read, recommended against by a number of generally
accepted guidelines like DRY, and just plain freaking dumb. So, why?

- Alf

Mr Flibble

unread,
Dec 27, 2019, 7:43:09 PM12/27/19
to
Taking your really bad analogy of DRY to its logical conclusion you can
only use a vector once in your entire program so you don't fucking
repeat yourself. Bad analogies are "just plain freaking dumb".

Alf P. Steinbach

unread,
Dec 28, 2019, 1:37:33 AM12/28/19
to
On 28.12.2019 01:42, Mr Flibble wrote:
> On 27/12/2019 19:05, Alf P. Steinbach wrote:
>> On 27.12.2019 17:38, Mr Flibble wrote:
>>>
>>> Egregious (std:: preferred).
>>
>> Why do you prefer to repeat a bit of text ad nauseam? It's more to
>> write, more to read, recommended against by a number of generally
>> accepted guidelines like DRY, and just plain freaking dumb. So, why?
>
> Taking your really bad analogy of DRY to its logical conclusion you can
> only use a vector once in your entire program so you don't fucking
> repeat yourself.  Bad analogies are "just plain freaking dumb".

I can agree with the last sentence.

Regarding the rest, consider:


#include <array>

void leigh()
{
const int board_size = 8;
std::array<std::array<int, board_size>, board_size> board =
{
std::array<int, board_size>{}, std::array<int, board_size>{},
std::array<int, board_size>{}, std::array<int, board_size>{},
std::array<int, board_size>{}, std::array<int, board_size>{},
std::array<int, board_size>{}, std::array<int, board_size>{}
};
(void) board; // Whatever
}

void alf()
{
using std::array;

const int width = 8;
const int height = width;

using Row = array<int, width>;
using Board = array<Row, height>;

Board board{};
(void) board; // Whatever
}


Here the two functions manage to create a local variable called `board`,
of the exact same type in the code as by your argumentation you would
have written it, and in corresponding code by me.

In the assumed-like-Leigh code the `std::` qualification and the type
builder `array` is repeated ad nauseam, because you argue that even when
it's known that all textual instances are a given text it should better
be spelled out; and the focus, what's communicated to a reader, is on
the details of the data representation and not on what it models.

In the more DRY (Don't Repeat Yourself) Alf code the relevant namespace
`std::` is mentioned only once; the type builder `array` is mentioned
only in a `using` declaration and for the two types that it builds here,
that is, three times; and the focus, what's communicated to a reader, is
on what the structure models.

- Alf

Mr Flibble

unread,
Dec 28, 2019, 10:51:47 AM12/28/19
to
Alf, using deliberate exaggeration to try to invalidate a person's
argument is disingenuous at best but I am sure you know this.

void real_leigh()
{
std::size_t const width = 8;
std::size_t const height = width;

using row = std::array<int, width>;
using board = std::array<row, height>;

Board board{};
(void) board; // Whatever
}

Now please stop being a cunt.

bol...@nowhere.org

unread,
Dec 28, 2019, 11:31:03 AM12/28/19
to
Or since board is just storing ints you could both make it even simpler still
using C99:

size_t const width = 8;
size_t const height = width;

typedef int Board[width][height];
Board board;

Just saying.


Mr Flibble

unread,
Dec 28, 2019, 12:15:25 PM12/28/19
to
Simpler isn't always better and one could argue that old C-style arrays
can make certain code that *uses* them more complicated versus
std::array usage. More or less the only use-case for C-style arrays in
modern C++ are dynamic arrays for allocating uninitialized buffers;
std::array is superior to C-style arrays for nearly all other use-cases
due to the container-like interface it offers with NO associated
overhead in offering it. Just saying.
0 new messages