Comparison syntax referring to the same variable

Asked

Viewed 236 times

10

Let me give you an example in C#:

namespace Compare
{
    class Program
    {
        static void Main(string[] args)
        {
            string name = "Girl";
            if(name == "Girl" || == "girl") //...
        }
    }
}

This form clearly contains an error, it is not possible to make the comparison this way, I should repeat the variable name and would look like this: if (name == "Girl" || name == "Lady").

  • Why programming languages do not allow doing so when we want to refer to the same variable?

Maybe there’s a reason, eventually I make that mistake because I think it would be the most logical way. Of course when we want to make the comparison, or other (&&, !=). Including other variables would be inevitable, I understand this.

I’ve used Javascript, PHP, C# and none allows this type of comparison.

4 answers

10


It is right in the challenge. It could exist, not with this syntax that is weird and maybe creates ambiguity, but another could.

Math is like that

In fact mathematics itself has a chain of operators. But a human can parse the expression with more context than a compiler.

Simple chaining can make it difficult to compiler creation and decrease their performance and even prevent the resolution of certain cases.

In fact the chaining could generate misinterpretation on the intention of the programmer. Nothing serious, nothing that doesn’t happen in other cases of language syntax, but it’s something they’d rather avoid. You probably would have to have certain restrictions of what you can use, for example not being able to mix operators.

Examples of what can be adopted

The most interesting cases would be:

x > 0 && x < 10

which could be written as

x between 0, 10

and also

x == 1 || x == 2

which would be simplified to

x in (1, 2)

The names could be replaced by symbols.

In fact there are less popular languages that adopt this type of syntax.

I find the design pattern (yes, it’s a Pattern design) so common it could be worth.

You can think of other syntaxes, even more generic. For example, it could have a symbol, for example $, where you use to indicate the name of the last variable used, it would already simplify. I’m not saying that this is good and there are no problems, just an idea. Many people will find it weird and less readable, essentially to save typing, which is silly to worry about.

Python lets do 0 < x < 10. In some languages this would be interpreted as (0 < x) < 10 and it would work, but it would give an unexpected result. The operation inside the parentheses would generate a boolean which would then be used to compare with 10. It has languages that can identify that a Boolean cannot mix with a number and adopt the behavior of chained operator, but it is an exception, it is complicated to deal with this in the compiler. And there are situations that the compiler would lose. There are worse situations, including that Python generates something possibly unexpected.

Characteristics that can generate bugs are usually avoided by languages.

Performance

One of the advantages of the operator in is that it is solved in compilation and does not generate running cost, and can even be generated a different algorithm depending on the amount of operands or other factors, unlike the one exposed by Isac that gives a solution that can be good in certain scenarios.

It’s not all flowers

But I see a problem that may be the reason for the more modern languages. I’m not going to talk about the older ones because they were rudimentary.

Everything you do in one language has consequences elsewhere. The more it complicates a point, it may be exponentially complicating other parts. Unless the functionality is completely orthogonal, which is rare, you’ll have to think of solutions to other points.

Overload of operators

If the operator in is an operator like any other he should have the ability to be overloaded like the others, right? Then the execution could not be optimized properly and would fall into the same commitment to use a function that does this.

You may think that in languages that do not have operator overload can do without problems. But if you do so, it practically prevents language from being overloaded in the future. Many features when placed in the language prevent others, so it is good to avoid certain things.

Of course you could make an exception and not have overload for certain operators. This already exists, but it can get weird in this case because the simple comparison has overload and the multiple has no?

Even if you have overload I think normal or specific optimizations may still make it worth using.

The same goes for the chained greatness comparator, the first example I showed.

Other problems

Certainly in a quick analysis I haven’t looked at all the problems that might have in this functionality. It’s possible they thought of others I didn’t realize.

Of course I think for everything has solution. The question is whether it is good enough.

Psychological factors

People are used to a syntax, when it introduces a new one there is always some difficulty of people to accept. Any language that does this will have the pecha to be weird, even if it is just a baseless perception. No one wants that in their language.

There are already controversies about the use of == which is easy to confuse with =.

Endnotes

Boolean expressions are independent and can be used anywhere a boolean value is expected. It’s common for people to think that comparisons can only be used in one if or while.

Some answers talk about Boolean algebra. Although the subject has to do with it, the question of the syntax of the operator has nothing to do with the algebra itself. No matter how the syntax generates a boolean result is what matters, the fact that it has this or that syntax matters nothing from the Boolean point of view and is not the reason for not having in the languages. It also has nothing to do with the generated Assembly code. Syntax is something independent.

C# 9

Now you can do something close to that, maybe even better:

name is "Girl" or "girl"

Behold working in the ideone (hoping to update version). And in the .NET Fiddle. Also put on the Github for future reference.

The other answer says this is impossible, so C# is miraculous.

Another novelty that should come in future versions is the ternary operator of comparison. Do not confuse it with the conditional ternary that already exists. That’s why I always said not to call the parole ternary. So you can do like Python.

  • 1

    I was waiting for the example of Python, until I saw him in his reply

  • Nice innovation from C#

7

The syntax adopted in the logical comparisons in the programming languages evolved from the fusion of different areas of knowledge, however, two are predominant as to the influence they had:

1) mathematics: the first computers were designed as machines for automation of arithmetic calculus, as we know, the simplest arithmetic operation always involves two factors: a + b

2) logic: with the studies of George Boole on pure logic in the nineteenth century a specific notation was developed which, although it did not anticipate the advent of computers, inspired the technical solutions for the automation of calculations.

In general, Boole’s (or Boolean) logic fundamentally advocates:

a) you always start with the idea that for a given statement about P there can only be one of two possibilities, true or false, nothing else.

b) from there you can form other statements, which must be true or false, combining them with the use of operators (and, or, xor, not)

How can you notice what inspired the modern syntax based on the simplest form of a logical comparison, ie between two factors.

Now you wonder why languages require you to repeat the variable as in the given example:

if(name == "Girl" || == "girl")

The answer is that this format violates the basic principle of comparing two factors and thus impossible for interpreters and compilers to infer that the comparison with "girl" refers to "name".

Modern languages therefore use a notation that does not allow interpreters and compilers to infer the meaning of logical comparisons.

However, there is nothing to prevent other programming languages from being built on principles other than traditional.

  • (About interpreting some boolean clauses) With the exception of and for some things with Python, as illustrated in Maniero’s reply

7

Why is it so?

This type of conditional structure is based on boolean algebra. Yes or no. True or false. One or zero. It works like this in BASIC (1964), C (1972), Java (1995) and other languages you can think of. The most standard structure is:

SE condição ENTÃO faça [SE NÃO faça2] FIM SE

It is mandatory that condição or become a boolean. A condição may be multiple and may use operators as equal, greater or equal, lesser or equal, lesser, greater and so on. Everything completely mathematical until then.

Your Java code, C#, C, C++, BASIC and any will be translated into machine code. See this Java code:

if (x >= y) {
    // cláusula 1
} else {
    // cláusula 2
}

It will be translated into something like this (pseudo-Assembly):

cmp (r1),(r2)    // compara os operandos nos respectivos endereços de memória apontados pelos registros r1 e r2
blt else         // pula para o else se r1 é menor que r2
   ...           // aqui o código da cláusula 1
bra end_if       // pule para o end_if
else:
   ...           // aqui o código da cláusula 2
end_if:

Machine code consists entirely of binary data, but structurally similar to Assembly code. Source

Perhaps the most directed, performative and yet mathematical way that language designers found to do conditional operations was in the first pattern I mentioned. And they’ve been doing it ever since.

It’s not a rule!

The rest is characteristic of language, but everything generates a common conditional structure after all. It is to facilitate reading and development, most of the time. What matters, as Maniero said, is to generate a boolean result.

Ruby

See what you can do in Ruby:

faça() if condição

I quoted to show that it can be different. Another example in Ruby:

x = 1 
unless x>=2
   puts "x é menor que 2"
 else
   puts "x é maior que 2"
end

Python

Python has chain comparisons, see:

if (0 < x < 10):
    # ...

I mean, in Python x < y <= z is what even x < y and y <= z.

Common Lisp

Common Lisp (and variants) has chained operators, but even more interestingly, see:

(< a b c d)

is the same as

(a < b < c < d)

These chain operations have existed since the BCPL, Basic Combined Programming Language, which influenced the C language.

.NET

I made a question here focused more on C# over comparative and method Contains(), when there is a tangle of possibilities to be compared with a single value, for example:

if(foo == "abc" || foo == "54" || foo == "23A" || foo == "3xe" || foo == "123") { ... }
// versus
if(new String[] {"abc", "54", "23A", "3xe", "123"}.Contains(foo)) { ... }

It is an interesting similar implementation, worth reading the good answers you have there if you want more on the subject.

6

Why programming languages do not allow doing so when we want to refer to the same variable?

The main reason, as I said in the commentary, is because each comparison has to have 2 operands, one left and one right operand.

It has to be something like:

operando1 comparador operando2

Where the comparator can be one of 6: <, <=, >, >=, ==, != In Javascript and PHP even has 2 extra comparators that can use the === and the !==

So what you’re trying to do is make an exception to the rule. Of course it would give the compiler to be able to interpret this special case that presented, but the creators of languages did not think it was relevant to create this exception, and could even generate ambiguity in reading.

You might think it makes it a lot harder if you have a case with a lot of comparisons:

if (name == "Girl" || name == "Lady" || name == "Miss" || name == "Girly" || 
    name == "Ma'am" || name == "Madam" || name == "Misses")

But that is not true, because if you have so many cases it means that you have misinterpreted your solution and that it would be better solved in another way:

Example (Javascript):

const validNames = ["Girl", "Lady", "Miss", "Girly", "Ma'am", "Madam", "Misses"];

if (validNames.indexOf(name) != -1)

const validNames = ["Girl", "Lady", "Miss", "Girly", "Ma'am", "Madam", "Misses"];

function validar(n){
  if (validNames.indexOf(n) != -1) console.log(n + " encontrado");
  else console.log(n + " não Encontrado");
}

validar("Lady");
validar("Rose");

This will allow you to exchange all ifs with N comparisons by a single indexOf and make all the code much easier to maintain. Imagine what it was like to have to exchange all these ifs spread across the program if you now had one more name to consider. In the solution I proposed I just had to add a new name to the array in a single location.

The same applies if you want to have a different action for each name type. In this case you can build a map with the names and functions to execute and call the one that matters based on the name.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.