Why no @ or $ operator in C++?

P

Peter

Just wondering... out of the "Shift + number"
characters only @ and $ have no reserved
meaning in C++ - why is that? Since they're
available, why weren't they used to represent
one of the operators so that the syntax could
be less context-sensitive?
 
V

Victor Bazarov

Just wondering... out of the "Shift + number"
characters only @ and $ have no reserved
meaning in C++ - why is that? Since they're
available, why weren't they used to represent
one of the operators so that the syntax could
be less context-sensitive?

Wrong newsgroup. Since operator syntax in C++ was essentially inherited
from C, you better ask in c.l.c. ;-)

It's quite possible that those characters are too specific to American
keyboards, and for a language to be accepted worldwide, it's better to
use culture-neutral symbols. But that's just a hypothesis.

V
 
S

Stefan Ram

Victor Bazarov said:
It's quite possible that those characters are too specific to American
keyboards, and for a language to be accepted worldwide, it's better to
use culture-neutral symbols. But that's just a hypothesis.

When one writes a preprocessor for C or C++, it always comes in handy
when there are some symbols free to be used for that preprocessor, as in:

@define example code
$error 21
`integer` x;

. (Of course, one must be careful, because these symbols can appear as
a part of a char literal, string literal, or comment in C++.)
 
V

Victor Bazarov

When one writes a preprocessor for C or C++, it always comes in handy
when there are some symbols free to be used for that preprocessor, as in:

@define example code
$error 21
`integer` x;

. (Of course, one must be careful, because these symbols can appear as
a part of a char literal, string literal, or comment in C++.)

I tried imagining other languages and the use of those symbols in them,
and could only recall @ in relation to pointers in Pascal... At the
same time I do seem to recall that they had some special meaning in a
couple of assembler languages I used to know. In some variant of BASIC
for instance the dollar sign following the variable name meant that the
variable had type "string" (or something like that).

V
 
S

Stefan Ram

Victor Bazarov said:
couple of assembler languages I used to know. In some variant of BASIC
for instance the dollar sign following the variable name meant that the
variable had type "string" (or something like that).

This was legal BASIC in 1978:

10 LET A$ = "alpha"
20 PRINT A$
30 END

. This is legal Java in 2014 (part of a compilation unit, not the whole unit):

final java.lang.String A$ = "alpha";
java.lang.System.out.println( A$ );
java.lang.System.exit( 0 );

. In fact, actually, I /am/ using a $-based preprocessor
right now. What I do really see in my editor window is:

..----------------------------------------------------------------
| File Edit Search View Window Help
..---------------------------------------------------------
| $include headers/java.xpp
|
| $if 1
|
| public class Main
| { public static void main( final java.lang.String[] args )
| { final java.lang.String A$ = "alpha";
| java.lang.System.out.println( A$ );
| java.lang.System.exit( 0 ); }}
|
| $endif
|
| $if 0
|
| public class Main
| {
...

I am using the preprocessor above simply to comment-out some
code with »$if 0«. (This preprocessor can detect that the
»A$« is not meant for him to process.)
 
J

James Kanze

On 4/18/2014 1:19 PM, Peter wrote:
Wrong newsgroup. Since operator syntax in C++ was essentially inherited
from C, you better ask in c.l.c. ;-)
It's quite possible that those characters are too specific to American
keyboards, and for a language to be accepted worldwide, it's better to
use culture-neutral symbols. But that's just a hypothesis.

If that were the case, we wouldn't have operators like |, nor
would the language use { or } (none of which are present on most
keyboards).

My guess (and my question to the original poster) is: what
should they mean? C++ have operators for every operation one
might reasonably want (and then some).
 
Ö

Öö Tiib

Just wondering... out of the "Shift + number"
characters only @ and $ have no reserved
meaning in C++ - why is that? Since they're
available, why weren't they used to represent
one of the operators so that the syntax could
be less context-sensitive?

Objective-C uses @ a lot. Currently mix of
Objective-C and C++ compiles. If C++ would use
@ for something there would be syntax ambiguities.

Symbol $ means "dollar"; most of planet does not
need dollar sign for anything and keyboards
have other symbols like ¤, £, ¥ or EURO instead there.
 
S

Stefan Ram

James Kanze said:
My guess (and my question to the original poster) is: what
should they mean? C++ have operators for every operation one
might reasonably want (and then some).

Some languages have an operator for

#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
 
P

Peter

My guess (and my question to the original poster) is: what

should they mean? C++ have operators for every operation one

might reasonably want (and then some).

I didn't mean to invent a new operator, I just wondered
why none of the two symbols mentioned by me were used
to denote one of already existing operators.
C and C++ are known for being context sensitive which
is one of the reasons why it's so hard to write a compiler
for them. With two extra symbols this context
sensitivity could at least have been reduced.
Example: & currently means three different things
in C++: a reference, an "address of" operator and "bit and".
If there were two symbols left, why weren't they used
by language creators to reduce some of this ambiguity
in favor of simpler grammar? An "address of" operator
could be, for example, @ (as someone noticed, it is
in Pascal). Perhaps $ could have been used to represent
a C++11 rvalue reference. Instead it was decided to reuse
the good old &&.
 
S

Stefan Ram

Peter said:
is one of the reasons why it's so hard to write a compiler
for them. With two extra symbols this context
sensitivity could at least have been reduced.
Example: & currently means three different things
in C++: a reference, an "address of" operator and "bit and".

When you write a C++ compiler, this will be the least of
your problems.
 
S

Stefan Ram

When you write a C++ compiler, this will be the least of
your problems.

I just wrote this simple example of a parser than can
disambiguate between unary and binary minus »-«.
(When I started to write it, I believed that this newsgroup
was comp.lang.c, so it became a C program.)

#include <stdio.h> /* printf */

static char const * source;
static int pos = 0;

static inline char get( int const move )
{ char result = source[ pos ]; pos += move; return result; }

static inline int numeral(){ return get( 1 )- '0'; }

static int prefix(){ int sign = 1;
while( '-' == get( 0 )){ get( 1 ); sign *= -1; } return sign * numeral(); }

static int diff(){ int result = prefix();
while( '-' == get( 1 ))result -= prefix(); return result; }

void test( char const * const s )
{ source = s; pos = 0; printf( "%s = %d\n", source, diff() ); }

int main( void )
{ test( "4-2)" ); test( "-4-2)" ); test( "4--2)" ); test( "-4--2)" );
test( "-4---2)" ); test( "--4--2)" ); }
 
Ö

Öö Tiib

Some languages have an operator for

#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);

James's question was more that 'a@b' or 'a$b' ... it is hard to imagine
context where those make sense. Certainly not in context of 'pow'?

Probably if people need 'pow' a lot in problem domain then that could be
handy to have some 'a¬b' instead of 'pow(a,b)'. When there is desire to
stay within ASCII then it could be 'a^^b'. Not perfect since 'a^b'
means "bitwise xor", 'a|b' means "bitwise or" and 'a||b' means "or" as
result some may intuitively think that 'a^^b' means "xor". However your
point is valid that someone somewhere could "reasonably want" it.
 
Ö

Öö Tiib

I didn't mean to invent a new operator, I just wondered
why none of the two symbols mentioned by me were used
to denote one of already existing operators.
C and C++ are known for being context sensitive which
is one of the reasons why it's so hard to write a compiler
for them.

C compiler is rather simple. Only maybe that almost
Turing-complete preprocessor is bit of fun and compiler writer
can make it inefficient since very few use preprocessor
metaprogramming. There are plenty of fully open source
stand-alone preprocessors available.

Difficulties with C++ are all those name lookups and resolutions
and that Turing-complete template system. Templates are used
more heavily than preprocessor so those must be efficient.

With such open source compiler like clang it is rather
pointless to write your own C or C++ compiler. If you need
a compiler for some odd architecture then better write
translator from LLVM to assembler of that architecture
plus port some open source C and C++ standard libraries
to it. Leftover effort you can use for your other hobbies
or for helping to improve clang.
With two extra symbols this context
sensitivity could at least have been reduced.

To me 'a @ b' or 'a $ b' mean intuitively nothing. So I have to
look them up anyway.
Example: & currently means three different things
in C++: a reference, an "address of" operator and "bit and".

Easy to make visual difference with white-space. For example:

* 'a&' means type "reference to" a
* 'a const&' means type "reference to const" a
* '&a' means "unary operator&" with parameter (a)
* 'a & b' means "binary operator&" with parameters (a,b)

Now just throw together static code analyzer that checks that
such white-space policy is followed in each commit to your repo
and the usage of '&' is clear in your code base.
If there were two symbols left, why weren't they used
by language creators to reduce some of this ambiguity
in favor of simpler grammar? An "address of" operator
could be, for example, @ (as someone noticed, it is
in Pascal). Perhaps $ could have been used to represent
a C++11 rvalue reference. Instead it was decided to reuse
the good old &&.

So '@a' means "rvalue reference to" a? Would not really
matter, I use "rvalue reference to" rather rarely in my
code. It is anyway simpler than with '&' since there are
no unary '&&' operators and also most coding standards
forbid overloading 'operator&&'.
 
S

Stefan Ram

I just wrote this simple example of a parser than can
disambiguate between unary and binary minus »-«.
(When I started to write it, I believed that this newsgroup
was comp.lang.c, so it became a C program.)

The C++ version:

#include <iostream>
#include <ostream>
#include <sstream>

template< typename scanner >struct parser
{ scanner s; parser( char const * s ): s{ s } {}
int numeral(){ return s.get() - '0'; }
int prefix(){ int sign = 1;
while( '-' == s.peek() ){ s.get(); sign *= -1; } return sign * numeral(); }
int start(){ int result = prefix();
while( '-' == s.get() )result -= prefix(); return result; }};

int main()
{ using p = ::parser< ::std::stringstream >;
auto test = []( char const * s ){ ::std::cout << p{ s }.start() << '\n'; };
test( "4-2" ); test( "-4-2" ); test( "4--2" ); test( "-4--2" );
test( "-4---2" ); test( "--4--2" ); test( "4-2-1" ); test( "4-2--1" ); }
 
Ö

Öö Tiib

Of course that wouldn't work for C.

Yes, multiplication with indirection are possibly written without
whitespace in some existing code so resolving it may need complex
parsing rules. Something like 'a -^ b' would likely break nothing.
 
S

Stefan Ram

Öö Tiib said:
Yes, multiplication with indirection are possibly written without
whitespace in some existing code so resolving it may need complex
parsing rules. Something like 'a -^ b' would likely break nothing.

Best approximation I can get in C++:

#include <iostream>
#include <ostream>
#include <cmath>

struct E { unsigned long long e; };
struct D { E e; };
constexpr E operator"" _( unsigned long long const e ){ return{ e }; }
D operator*( E const e ){ return{ e }; }
double operator*( double const x, D const d ){ return ::std::pow( x, d.e.e ); }

int main(){ ::std::cout << 2**10_ << '\n'; }

1024
 
S

Stefan Ram

int main(){ ::std::cout << 2**10_ << '\n'; }

When writing a parser for exponentiation, one needs to know
that exponentiation is right-associative, while division is
left-associative. I just wrote this tiny parser to show how
this might be implemented:

#include <iostream>
#include <ostream>
#include <map>
#include <functional>
#include <cmath>
#include <sstream>
#include <cstring>

::std::map< char, ::std::function< double( double, double )>> ex
{ { '^', []( double const x, double const y )->double
{ return ::std::pow( x, y ); }},
{ '*', []( double const x, double const y )->double{ return x * y; }},
{ '/', []( double const x, double const y )->double{ return x / y; }},
{ '+', []( double const x, double const y )->double{ return x + y; }},
{ '-', []( double const x, double const y )->double{ return x - y; }}};

::std::map< char, bool >left_associative
{ { '^', false }, { '*', true }, { '/', true }, { '+', true }, { '-', true }};

template< typename scanner >struct parser
{ scanner s; parser( char const * s ): s{ s } {}
char check( char const * const op )
{ return ::std::strchr( op, static_cast< char >( s.peek() )) ?
static_cast< char >( s.get() ): 0; }
double numeral(){ return s.get() - '0'; }
double prefix(){ int sign = 1;
while( '-' == s.peek() ){ s.get(); sign *= -1; } return sign * numeral(); }
double parse( char const * const op, double( ::parser< scanner >::*next ) () )
{ double result =( this->*next )();
for( char sym; sym = check( op ); )result = ex[ sym ]
( result, left_associative[ sym ]?( this->*next )(): parse( op, next ));
return result; };
double power(){ return parse( "^", &::parser< scanner >::prefix ); }
double product(){ return parse( "*/", &::parser< scanner >::power ); }
double sum(){ return parse( "+-", &::parser< scanner >::product ); }
double start(){ return sum(); }};

int main()
{ using p = ::parser< ::std::stringstream >;
auto test = []( char const * s ){ ::std::cout << p{ s }.start() << '\n'; };
test( "2^2^3/2/2" ); test( "2+2*2^2^-3" ); }

64
4.18102
 
J

J. Clarke

Victor Bazarov said:
couple of assembler languages I used to know. In some variant of BASIC
for instance the dollar sign following the variable name meant that the
variable had type "string" (or something like that).

This was legal BASIC in 1978:

10 LET A$ = "alpha"
20 PRINT A$
30 END

. This is legal Java in 2014 (part of a compilation unit, not the whole unit):

final java.lang.String A$ = "alpha";
java.lang.System.out.println( A$ );
java.lang.System.exit( 0 );

. In fact, actually, I /am/ using a $-based preprocessor
right now. What I do really see in my editor window is:

.----------------------------------------------------------------
| File Edit Search View Window Help
.---------------------------------------------------------
| $include headers/java.xpp
|
| $if 1
|
| public class Main
| { public static void main( final java.lang.String[] args )
| { final java.lang.String A$ = "alpha";
| java.lang.System.out.println( A$ );
| java.lang.System.exit( 0 ); }}
|
| $endif
|
| $if 0
|
| public class Main
| {
...

I am using the preprocessor above simply to comment-out some
code with »$if 0«. (This preprocessor can detect that the
»A$« is not meant for him to process.)

FWIW, Powershell, the "official" scripting language for Windows,
prefixes all variable names with $.
 
J

James Kanze

Le samedi 19 avril 2014 12:17:17 UTC+1, Öö Tiib a écrit :
Some languages have an operator for
#include <math.h>
double pow(double x, double y);
float powf(float x, float y);
long double powl(long double x, long double y);
[/QUOTE]

Initially, C wasn't designed for numerical applications, so pow
wasn't considered important enough for an operator. (The
precedent was there: Fortran has **, for example.)
James's question was more that 'a@b' or 'a$b' ... it is hard to imagine
context where those make sense. Certainly not in context of 'pow'?

There was, at one point, a suggestion that C++ adopt a power
operator; the two character sequence *^ was proposed.
(Fortran's ** couldn't be used, because it could occur in legal
programs already. And ^, meaning power for floating point
types, but exclusive or for integral types, had the wrong
precedence.) In the end, the numerics experts on the committee
said that they had no problem with using pow as a function.
Probably if people need 'pow' a lot in problem domain then that could be
handy to have some 'a¬b' instead of 'pow(a,b)'. When there is desire to
stay within ASCII then it could be 'a^^b'. Not perfect since 'a^b'
means "bitwise xor", 'a|b' means "bitwise or" and 'a||b' means "or" as
result some may intuitively think that 'a^^b' means "xor". However your
point is valid that someone somewhere could "reasonably want" it.

Curiously, I don't remember ^^ being suggested. The people
asking for pow all came from a Fortran background, and
originally wanted **. (IIRC, at least. This is all quite some
time back, well before C++98 became a standard.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top