What does the "operator <" syntax mean? - c++11

I am trying to learn C++ STL..I came across this syntax,not able to figure out what the whole line means!
struct student{
int id,pts;
bool operator < (student x) const{
return pts>x.pts;
}
}a[150000];

it is defining a "less than" operator for the struct student, so that people can write:
student one, two;
bool b = one < two;

operator < is a name to be defined, just like foo or bar. It behaves just like an identifier.
bool operator < (student x) const declares a function as bool foo (student x) const would.
The effect is to define usage of the < operator between student objects. The connection to the STL is that templates related to ordering of objects use expressions like a < b to perform the ordering. This comes up in algorithms like std::sort and containers like std::map.
That particular definition sorts students by points, which isn't a very good system for sorting students. Facilities like sort and map always provide an alternative to operator <, where you can pass a more specific function, say one called less_points. Also, since that definition of operator < uses the > operator internally (without reversing the left- and right-hand sides), it will sort in descending order whereas the usual convention is to use ascending order.
Note, it's common to define operator < or operator == without defining >, !=, or the other relational operators. The standard library only ever cares about < and ==, and boilerplate to get the rest is usually wasted. Likewise it's a good convention to avoid using relations besides < and == on objects that might not be numbers.

operator< allows comparing two students, and in this example, it compares only by pts.
struct student{
int id,pts;
bool operator < (student x) const{
return pts>x.pts; // must be pts<x.pts
}
}a[150000];
lest should it work the other way (operator >), the implementation must use operator '<'
As a good practice, please consider adding custom definition for operator > and operator=, because the comparison is based only on pts (by the definition of operator <)
For the sake of minimal completeness and logical correctness when using comparison operators, please consider adding custom definition for operators > and ==
struct student{
int id,pts;
bool operator < (student x) const{
return pts<x.pts;
}
bool operator > (student x) const{
return pts>x.pts;
}
bool operator == (student x) const{
return pts == x.pts;
}
}a[150000];

Related

Is it possible to generate an equality function based on the data to be compared?

Two Booleans are equal if the're the same value, two numbers similarly. Two sets are equal if they have the same elements. In case of checking two sets for equality we can use the following scheme/racket function:
(define (same-set? l1 l2)
(and (subset? l1 l2) (subset? l2 l1)))
How would such a function be generated automatically? Can it be generated for arbitrary data type?
The basic properties of an equivalence relation are:
Substitution property: For any quantities a and b and any expression F(x), if a = b, then F(a) = F(b) (if both sides make sense, i.e. are well-formed).
Some specific examples of this are:
For any real numbers a, b, and c, if a = b, then a + c = b + c (here F(x) is x + c);
For any real numbers a, b, and c, if a = b, then a − c = b − c (here F(x) is x − c);
For any real numbers a, b, and c, if a = b, then ac = bc (here F(x) is xc);
For any real numbers a, b, and c, if a = b and c is not zero, then a/c = b/c (here F(x) is x/c).
Reflexive property: For any quantity a, a = a.
Symmetric property: For any quantities a and b, if a = b, then b = a.
Transitive property: For any quantities a, b, and c, if a = b and b = c, then a = c.
Is it possible to generate a function that obeys the above properties? Would that be enough? Could knowing the type of data help?
If you have any ideas on how to improve this question or tag it please comment.
I just want to expand on #Sorawee Porncharoenwase's answer a bit. They mentioned two kinds of equality, referential equality with eq?, and structural equality with equal?.
These different notions of equality should all follow the basic requirements of reflexivity, symmetry, and transitivity. But what sets them apart from each other is the guarantees that they give when they return true or false.
Some useful classes of equality to keep in mind are are reference-equality, structural-equality for all-time, structural-equality for the current time, and domain-specific equivalences.
Reference equality
The eq? function implements reference equality, and it has the strongest guarantees when it returns true, but when it returns false you haven't learned much.
(eq? x y) implies that x and y are literally the same object, and that any operation on x could be replaced with the same on y, including mutation. One thing that helped explain this to me was in the book Realm of Racket, saying that if you shave x, then y will also be shaved because it's the same object.
However, when (eq? x y) returns false that's pretty weak sauce. On the many data structures that involve allocating memory, eq? can return false simply because the pointers are different, even if they're immutable and everything else is the same.
This can be provided automatically by the programming language because it's really not much more than pointer-equality, and it doesn't have to generate any new behavior for new data structures.
Structural Equality for All-Time
This notion of equality is not currently well-supported by base Racket or standard Scheme, although libraries such as Rackjure can provide limited versions of this with functions like egal?. It implements reference equality on mutable data structures, but structural equality on immutable data structures.
This is meant to provide the guarantee that if (egal? x y) returns true now, then it has been true in the past and will continue to be true in the future as long as x and y both exist.
This can be provided automatically by the programming language as long as the language allows you to specify which data structures are immutable vs mutable, and enforces the immutability.
I'm not sure, but chaperone-of? may also be an example of following the ideas of "Structural Equality for All-Time", except that chaperone-of? isn't symmetric (and a naive symmetric-closure would lose transitivity).
If you want to read more, see Types of Equality in Pyret or Equal Rights for Functional Objects.
Structural Equality for the Current Time
The equal? function implements structural equality for the current time. This means two mutable data structures can be equal now if they currently have all equal components, even if they weren't equal in the past or won't be in the future due to mutation.
This can be provided automatically by the programming language as long as it always knows all the sub-parts of data contained within the data-structures.
Domain-specific Equivalences
For example for the domain of numbers and math, you might want the inexact number 2.0 to be equivalent to the exact integer 2. For the domain of string search, you might want case-insensitive equivalence for strings and characters so that A and a are equivalent. For the domain of sets, you might want order to be irrelevant so that (a b) and (b a) are equivalent.
Each domain is different, so this requires more effort on each domain. The programming language can't read your mind.
Two Booleans are equal if the're the same value, two numbers similarly. Two sets are equal if they have the same elements.
These are useful equalities, but they are not the only equalities that you can create. For instance, you can consider two numbers to be equal when their parities (odd/even) are the same. Or you can consider every number to be equal to each other.
How would such a function be generated automatically?
In general, it's not possible, because it depends on your intention. And no one can read your mind.
Is it possible to generate a function that obeys the above properties?
The answer is trivially yes. At the very least, you have (lambda (x y) #t), which says that every object is equal to every other object. It satisfies the equivalence relation properties, though it's totally useless.
For a non-trivial equality that works on all kinds of values, you have referential equality eq? which obeys the equivalence relation property (it could give you a weird result if you are using the unsafe API IIUC, but that's off-topic).
equal? can be used for structural equality on several values such as lists and those that are instances of a default transparent struct, and it also cooperates with custom equality that users provide. This is usually what you want to use in Racket.
Yes, it is definitely possible. Some programming languages allow for automatic equality function synthesis. Swift is a such example.
Without automatic synthesis, the developer has to write code for the equality, e.g., consider a struct:
struct Country: Equatable {
let name: String
let capital: String
var visited: Bool
static func == (lhs: Country, rhs: Country) -> Bool {
return lhs.name == rhs.name &&
lhs.capital == rhs.capital &&
lhs.visited == rhs.visited
}
}
With Swift 4.1 and higher, this is no longer necessary. The compiler generates the equality function for you:
struct Country: Equatable { // It's enough to just declare that the type is `Equatable` and the compiler do the rest
let name: String
let capital: String
var visited: Bool
}
Let's test it:
let france = Country(name: "France", capital: "Paris", visited: true)
let spain = Country(name: "Spain", capital: "Madrid", visited: true)
if france == spain { ... } // false
Update:
Even after Swift 4.1, it's possible to override the default implementation with own, custom logic. For example:
struct Country: Equatable {
let name: String
let countryCode: String
let capital: String
var visited: Bool
static func == (lhs: Country, rhs: Country) -> Bool {
return lhs.countryCode == rhs.countryCode
}
}
So, the developer is always in control. The equality won't be synthesised automatically, the developer has to add Equatable to the struct declaration. If after that they're not satisfied with the default implementation, or if it couldn't be inferred, there is always an option to override compiler's intention and provide a customized variant.

Sign computation with a macro

What the following expression computes, exactly?
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
what yields if x is zero, less than zero, more than zero?
I guess I know the answer, but I'd like to check for clarity...
Thank you
EDIT: added missing parenthesis
EDIT: more info here
First, the macro doesn't compute anything. It is substituted into a source code, expanded, and the resulting text gets compiled. What the resulting text is, depends on the way you use the macro, especially on what parameter you give.
Second, the macro lacks one closing paren, so it probably would not give you a meaningful expression to be compiled.
Third, even when you add the lacking paren:
#define SIGN(x) ((x < 0) ? -1 : (x > 0))
it is possible you get unexpected results if you use the macro in a non-simplest way. For example,
SIGN(a ^ b)
would result in
((a ^ b < 0) ? -1 : (a ^ b > 0))
which is interpreted in C and C++ as
((a ^ (b < 0)) ? -1 : (a ^ (b > 0)))
which certainly is not what we intend.
You should add parentheses to avoid unwanted operators binding – for:
#define SIGN(x) (((x) < 0) ? -1 : ((x) > 0))
the above example will yield a sensible expression
(((a ^ b) < 0) ? -1 : ((a ^ b) > 0))
but that still doesn't protect you against unwanted double increment/decrement in case of plus-plus or minus-minus operators or double execution of a function in case the expression substituted for x contains a function call.
It does exactly what you probably think it does, gives -1 for negative numbers, 0 for zero, and 1 for positive numbers.
However, you should generally avoid function-like macros since they will not do what you expect if, for example, you try to calculate SIGN(value++). Since they're simple text substitutions, that would resolve to:
((value++ < 0) ? -1 : (value++ > 0)
You're far better off just using real functions and letting the compiler inline them if it decides it's worth it. You can also suggest to the compiler that inlining it, with the inline keyword, but keep in mind it is a suggestion.
That macro got a stray parenthesis.
It looks like it is meant to be an implementation of signum function, which returns -1, 1 or 0 depending on value of argument.
For sake of being safe and writing C++ code, it is prudent
to replace macro by template, similar to
template <class T>
int SIGN( T x )
{
return (x < T(0)) ? -1 : (x > T(0));
}
First comparision is argument of trenary operator ?:. Ternary would return -1 if expression evaluates to true , i.e. x is less than 0, otherwise it would return result of x > T(0).
That expression would evaluated to 0 if x equals to 0, otherwise it would be evaluated to 1.
Note that my implementation is not ideal, you can find better implementation elsewhere on SO.
An alternative expression can be:
return (T(0)<x) - (T(0)>x);
Which may be more effective with platforms that implement certain CPU instructions
If you use it with values only and not expressions that macro will produce -1, 0, 1, otherwise you may have serious problems. The tricky part is (x>0). Lets read the standard:
5.9 Relational operators [expr.rel]
The operators < (less than), > (greater than), <= (less than or equal
to), and >= (greater than or equal to) all yield false or true. The
type of the result is bool.
and
3.9.1 Fundamental types [basic.fundamental]
Values of type bool are either true or false. Values of type bool participate in integral promotions (4.5).
Thus x>0 is either true or false.
4.5 Integral promotions [conv.prom]
A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.
and is promoted to either 1 or 0 (respectively).

Defining boolean logic operators(v, ^, XOR, ->, <->)

Say we have bool true = (P v Q) -> R
How would I define an operator(or a function), so that the symbols(v, ^, XOR, ->, <->), would call the function that would perform the logic?
So, in example: bool true = P v Q, would call bool or(bool a, bool b)
It is not possible to define arbitrary infix operators in C++, and you also can’t use the name true as a variable name.
However, C++ already provides || for or, && for and, ^ or != for xor (for bools, they’re equivalent), and ! for not. If you want logical implication you’d best use !P || Q, and if you want iff, you should use P == Q.

Evaluation functions and expressions in Boolean expressions

I am aware how we can evaluate an expression after converting into Polish Notations. However I would like to know how I can evaluate something like this:
If a < b Then a + b Else a - b
a + b happens in case condition a < b is True, otherwise, if False a - b is computed.
The grammar is not an issue here. Since I only need the algorithm to solve this problem. I am able evaluate boolean and algebraic expressions. But how can I go about solving the above problem?
Do you need to assign a+b or a-b to something?
You can do this:
int c = a < b ? a+b : a-b;
Or
int sign = a < b ? 1 : -1;
int c = a + (sign * b);
Refer to LISP language for S-express:
e.g
(if (> a b) ; if-part
(+ a b) ; then-part
(- a b)) ; else-part
Actually if you want evaluate just this simple if statement, toknize it and evaluate it, but if you want to evaluate somehow more complicated things, like nested if then else, if with experssions, multiple else, variable assignments, types, ... you need to use some parser, like LR parsers. You can use e.g Lex&Yacc to write a good parser for your own language. They support somehow complicated grammars. But if you want to know how does LR parser (or so) works, you should read into them, and see how they use their table to read tokens and parse them. e.g take a look at wiki page and see how does LR parser table works (it's something more than simple stack and is not easy to describe it here).
If your problem is just really parsing if statement, you can cheat from parser techniques, you can add empty thing after a < b, which means some action, and empty thing after else, which also means an action. When you parsed the condition, depending on correctness or wrongness you will run one of actions. By the way if you want to parse expressions inside if statement you need conditional stack, means something like SLR table.
Basically, you need to build in support for a ternary operator. IE, where currently you pop an operator, and then wait for 2 sequential values before resolving it, you need to wait for 3 if your current operation is IF, and 2 for the other operations.
To handle the if statement, you can consider the if statement in terms of C++'s ternary operator. Which formats you want your grammar to support is up to you.
a < b ? a + b : a - b
You should be able to evaluate boolean operators on your stack the way you currently evaluate arithmetic operations, so a < b should be pushed as
< a b
The if can be represented by its own symbol on the stack, we can stick with '?'.
? < a b
and the 2 possible conditions to evaluate need to separated by another operator, might as well use ':'
? < a b : + a b - a b
So now when you pop '?', you see it is the operator that needs 3 values, so put it aside as you normally would, and continue to evaluate the stack until you have 3 values. The ':' operator should be a binary operator, that simply pushes both of its values back onto the stack.
Once you have 3 values on the stack, you evaluate ? as:
If the first value is 1, push the 2nd value, throw away the third.
If the first value is 0, throw away the 2nd and push the 3rd.

Extending Immutable types (or: fast cache for immutable types) in OCaml

I have a recursive immutable data structure in ocaml which can be simplified to something like this:
type expr =
{
eexpr : expr_expr;
some_other_complex_field : a_complex_type;
}
and expr_expr =
| TInt of int
| TSum of (expr * expr)
| TMul of (expr * expr)
It's an AST, and sometimes it gets pretty complex (it's very deep).
there is a recursive function that evaluates an expression. For example, let's say,
let rec result expr =
match expr.eexpr with
| TInt i -> i
| TSum (e1, e2) -> result e1 + result e2
| TMul (e1, e2) -> result e1 * result e2
Now suppose I am mapping an expression to another expression, and I need to constantly check the result of an expr, sometimes more than once for the same expr, and sometimes for expressions that were recently mapped by using the pattern
{ someExpr with eexpr = TSum(someExpr, otherExpr) }
Now, the result function is very lightweight, but running it many times for a deep AST will not be very optimized. I know I could cache the value using a Hashtbl, but AFAIK the Hashtbl will only do structural equality, so it will need to traverse my long AST anyway.
I know the best option would be to include a probably immutable "result" field in the expr type. But I can't.
So is there any way in Ocaml to cache a value to an immutable type, so I don't have to calculate it eagerly every time I need it ?
Thanks!
Hash-cons the values of expr_expr. By doing this structurally equal values in your program will share exactly the same memory representation and you can substitute structural equality (=) by physical equality (==).
This paper should get you quickly started on hash-consing in OCaml.
You can use the functorial interface to control the kind of equality used by the hash table. I believe the semantics of (==) are legitimate for your purposes; i.e., if A == B then f A = f B for any pure function f. So you can cache the results of f A. Then if you find a B that's physically equal to A, the cached value is correct for B.
The downside of using (==) for hashing is that the hash function will send all structurally equal objects to the same hash bucket, where they will be treated as distinct objects. If you have a lot of structurally equal objects in the table, you get no benefit from the hashing. The behavior degenerates to a linear search.
You can't define the hash function to work with physical addresses, because the physical addresses can be changed at any time by the garbage collector.
However, if you know your table will only contain relatively few large-ish values, using physical equality might work for you.
I think you can merge the two ideas above : use hash-consing-like techniques to get the hash of the "pure expression" part of your data, and use this hash as key in the memoization table for the eval function.
Of course this only works when your eval function indeed only depends on the "pure expression" part of the function, as in the example you gave. I believe that is a relatively general case, at least if you restrict yourself to storing the successful evaluations (that won't, for example, return an error including some location information).
Edit: a small proof of concept:
type 'a _expr =
| Int of int
| Add of 'a * 'a
(* a constructor to avoid needing -rectypes *)
type pure_expr = Pure of pure_expr _expr
type loc = int
type loc_expr = {
loc : loc;
expr : loc_expr _expr;
pure : pure_expr (* or any hash_consing of it for efficiency *)
}
(* this is where you could hash-cons *)
let pure x = Pure x
let int loc n =
{ loc; expr = Int n; pure = pure (Int n) }
let add loc a b =
{ loc; expr = Add (a, b); pure = pure (Add(a.pure, b.pure)) }
let eval =
let cache = Hashtbl.create 251 in
let rec eval term =
(* for debug and checking memoization *)
Printf.printf "log: %d\n" term.loc;
try Hashtbl.find cache term.pure with Not_found ->
let result =
match term.expr with
| Int n -> n
| Add(a, b) -> eval a + eval b in
Hashtbl.add cache term.pure result;
result
in eval
let test = add 3 (int 1 1) (int 2 2)
# eval test;;
log: 3
log: 2
log: 1
- : int = 3
# eval test;;
log: 3
- : int = 3

Resources