Useless instructions

From Rosetta Code
Useless instructions is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Showcase an instruction or function built into the language, that is made redundant by another instruction also built into the language. It can be limited to a specific way that function is used, e.g. printing a null string, but try not to make it that obvious.

NOP and any instructions or functions that are intended to do nothing do not count.



6502 Assembly

CMP #0 is nearly completely useless, as most 6502 instructions do this implicitly. It can be handy when you need to check equality to zero after a different register was altered, and in that scenario using PHP/PLP to save and restore the condition codes would be impractical, but these situations are few and far between.

myLoop:
;do stuff here
dex
;cpx #0    ;this isn't needed since the zero flag will be set if x=0
bne myLoop ;if x != 0, jump back to myLoop

68000 Assembly

CLR.L Dn sets an entire 32-bit register to 0x00000000. However, MOVEQ #0,Dn does the same thing but faster. The only advantage CLR Dn has is that it can directly clear memory locations.

8086 Assembly

xor ax,ax (or any other data register) takes fewer bytes to encode than mov ax,0 and achieves the same result. The only difference is that mov ax,0 doesn't set the flags, which can be used to the programmer's advantage when sequencing operations.

Action!

The Action! language has four fundamental data types, BYTE, CHAR, INT and CARD. The first two can be used interchangably and are 8-bit unsigned integers. This is presumably for documentation purposes, however the language also has a macro facility that would allow the programmer to DEFINE CHAR="BYTE" or DEFINE BYTE="CHAR" if only one was available.

Ada

The Ada Language Reference Manual Appendix J explains all the features of the language which are largely redundant and are discouraged in newly developed source code. The features are:

- Renaming of library units
- Allowed Replacement of Characters
- Reduced Accuracy Subtypes
- The Constrained Attribute
- The package ASCII defined within the package Standard
- The exception Numeric_Error
- At Clauses
- Interrupt Entries
- Mod Clauses
- The Storage_Size Attribute
- Specific Suppression of Checks
- The Class Attribute of Untagged Incomplete Types
- Pragma Interface
- Dependence Restriction Identifiers
- Character and Wide_Character Conversion Functions
- Aspect-related Pragmas

The full description of these obsolescent features is described in [1]

ALGOL 68

Works with: ALGOL 68G version Any - tested with release 3.0.1.win32

As well as being able to write IF TRUE THEN SKIP ELSE some code that will never be executed FI and WHILE FALSE DO some code that will never be executed OD, as in other languages shown here, Algol 68 has a feature that was presumably intended to aid portability (though whether it does in practice is another matter...):
Algol 68 has a notionally infinite number of integer, real and comples types. THe standard types INT, REAL and COMPL, can have an arbitrary number of LONG or SHORT prefixes to indicate larger or smaller types. Whether these are actually larger or smaller depends on the implementation - no warning is issued (at least, not in Algol 68G) to indicate that e.g. LONG LONG LONG REAL is not longer than LONG LONG REAL. In addition, there are "environment enquiries" that will reveal how big the types are, so e.g. max int is the largest INT value, long max int is the largest LONG INT value, etc. An arbitrary number of long and short prefixes can be applied.

As this sample shows, Algol 68G has only three sies of integer. The precission of LONG LONG INT can be specified by a pragmatic comment. The value shown here is the default.
Algol 68G has 64 bit INT and 128 bit LONG LONG INT. In previous versions, INT was 32 bit and LONG INT had a precision of 35 decimal digits.

print( (    long long long max int, newline ) );
print( (         long long max int, newline ) );
print( (              long max int, newline ) );
print( (                   max int, newline ) );
print( (             short max int, newline ) );
print( (       short short max int, newline ) );
print( ( short short short max int, newline ) );
print( ( short short short short short short short short short short
         short short short short short short short short short short
         short short short short short short short short short short
         short short short short short short short short short short
         short short short short short short short short short short max int, newline ) )
Output:
+999999999999999999999999999999999999999999999999999999999999999999999999
+999999999999999999999999999999999999999999999999999999999999999999999999
+170141183460469231731687303715884105727
+9223372036854775807
+9223372036854775807
+9223372036854775807
+9223372036854775807
+9223372036854775807

Applesoft BASIC

Many ways of printing an empty string.

?;:?"";:?"";"";:?;;;;;

AWK

# syntax: GAWK -f USELESS_INSTRUCTIONS.AWK
BEGIN {
# create an array with two elements
    n = split("item1,item2",array,",")
# delete array by removing one element at a time
    for (i=1; i<=n; i++) { delete array[i] }
# delete entire array; available in "old" awk onward
    split("",array)
# delete entire array; became available in "new" awk; redundant
    delete array
}

C

C can boast (if that's the right word) analogous redundant constructions to the Go and Wren examples though you might get warnings with some compilers. AFAIK creating an empty struct is also useless and may produce a warning or even an error as it's technically non-standard.

However, C has a more obvious form of redundancy in the shape of the 'auto' keyword. This was inherited from the 'B' language where it was needed to declare a local variable though is never needed in C itself.

Another keyword which is teetering on redundancy is 'register' whose purpose is to suggest to the compiler that it should store a variable in a CPU register rather than memory. However, modern optimizing compilers don't need such a suggestion and will use CPU registers anyway if they deem it appropriate. But it may still be relevant in embedded system programming so it can't be said to be completely redundant at the present time.

#include <stdio.h>
#include <stdbool.h>

void uselessFunc(int uselessParam) { // parameter required but never used
    auto int i; // auto redundant 

    if (true) {
        // do something
    } else {
        printf("Never called\n");
    }

    for (i = 0; i < 0; ++i) {
        printf("Never called\n");
    }

    while (false) {
        printf("Never called\n");
    }

    printf(""); // no visible effect but gcc 9.3.0 warns against it

    return; // redundant as function would return 'naturally' anyway
}

struct UselessStruct {
    // no fields so effectively useless and apparently non-standard in any case
};

int main() {
    uselessFunc(0);
    printf("Working OK.\n");
}
Output:
Working OK.

F#

printfn "%s" ("Nigel "^"Galloway")
printfn "%s" ("Nigel "+"Galloway")
Output:
main.fs(1,23): warning FS0062: This construct is for ML compatibility. Consider using the '+' operator instead. This may require a type annotation to indicate it acts on strings. This message can be disabled using '--nowarn:62' or '#nowarn "62"'.
> mono main.exe
Nigel Galloway
Nigel Galloway

Factor

Factor uses a data stack to pass arguments to functions. Factor provides at least five ways to arrange the stack, all five of which can make the other four redundant.

To get the data stack from 1 2 3 to 1 2 2 3 1 we could:

Use stack shuffle words:

dupd reach

Use data flow combinators:

[ ] keepdd [ [ ] [ ] bi ] 2dip

Use local variables:

[let :> ( a b c ) a b b c a ]

Use dynamic variables:

SYMBOLS: a b c ;
c set b set a set a get b get b get c get a get

Use shuffle( syntax:

shuffle( a b c -- a b b c a )

Go

I can't recall any language features or standard library methods in Go which are completely redundant either by design or due to subsequent developments. Moreover, the compiler does a lot to prevent unintentional redundancy by flagging unused packages, unused variables and unreachable code.

However, nothing's perfect and the analogous redundant constructions which are allowed in Wren are not picked up by the Go compiler either as the following program shows.

package main

import (
    "fmt"
)

type any = interface{}

func uselessFunc(uselessParam any) { // parameter required but never used
    if true {
        // do something
    } else {
        fmt.Println("Never called")
    }

    for range []any{} {
        fmt.Println("Never called")
    }

    for false {
        fmt.Println("Never called")
    }

    fmt.Print("") // no visible effect

    return // redundant as function would return 'naturally' anyway
}

type NotCompletelyUseless struct {
    /*
       On the face of it this struct is useless because:
       (1) it has no fields
       (2) there are no associated methods
       (3) there is no inheritance in Go

       However, it's not in fact completely useless because:
       (4) it can be used as a zero length value in a map to emulate a set
    */
}

func main() {
    uselessFunc(0)
    set := make(map[int]NotCompletelyUseless)
    set[0] = NotCompletelyUseless{}
    set[0] = NotCompletelyUseless{} // duplicate key so not added to set
    fmt.Println(set)
}
Output:
map[0:{}]

J

Here, we will focus on J's verb >:. This has two meanings, and both of them are redundant within the language.

First, X >: Y tests whether X is greater than or equal to Y. And, J has several other ways of accomplishing this same task. For example, if X is greater than or equal to Y, then Y is less than or equal to X, so an equivalent expression would be Y <: X. Another approach would be to test that X is not less than Y, which might be expressed as -.X < Y

Second, >: Y increments the value obtained from Y (it does not modify Y). And, J also has several other ways of accomplishing this task. For example: 1+Y. Or, we could express this in polynomial form as 1 1 p. Y, or we could subtract negative 1. Etc.

J has many other equally useless instructions, of course.

jq

The following remarks apply to both the C and Go implementations of jq.

jq is fundamentally a stream-oriented language, but the collection of built-in functions (in builtin.jq) includes array-oriented definitions for the sake of familiarity and/or convenience. This duality results in what could be considered redundancies.

For example, consider the 'any' and 'all' functions, all versions of which have short-circuit semantics. The array-oriented versions of these functions are defined in terms of the more fundamental stream-oriented functions, making the redundancy plain to see:

def all: all(.[]; .);

def any: any(.[]; .);

Julia

In julia the function `count()` can be used to count the true values in an array. Since in julia a `Bool` boolean is just an `Int` type, with 0 == false and 1 == true, the Julia `sum()` function and the `count()` function are functionally identical when applied to arrays of `Bool` type. This makes the `count()` function redundant except to better express intent to count rather than add.

array = [true, true, true, false, false, true]

@show count(array)  # count(array) = 4
@show sum(array)    # sum(array) = 4

Nim

In Nim, for an integer “x”, inc x, 3 and x += 3 are equivalent. But this is true only for integers. If “x” is a float, the only valid statement is x += 3. And if “x” is a bool or an enum, we can write inc x but not, of course, x += 1.

So, this is not really a good example of useless instruction.

There is a better example for a string or a sequence “s”, where s.add val and s &= val are equivalent.

Also, when defining a type with variants, when a branch doesn’t contain any field, we can use the keyword discard (as in a case statement) or the value nil.

type T = object
  case i: 0..2
  of 0: value: int
  of 1: discard
  of 2: nil

But, as discard is used as empty statement and nil is used as null value for references and pointers, we cannot say that they are useless even if they are synonyms in one context.

Perl

The mind-set behind the task runs counter to the Perl philosophy of TIMTOWTDI (there's more than one way to do it). Non-orthogonality is considered a feature, not a bug.

Phix

The five core builtin types form a natural hierarchy, so you can store an integer in a variable declared as an integer or a number (aka atom), the latter in an object, and a string in a string or a sequence, and the latter in an object. So, apart from error reporting, you don't actually need any data types other than "object".
Phix supports at least 45 different ways of expressing the same simple integer value, from binary to base 36, and that is before even considering string versions of it. For instance there is no difference whatsoever between 'A' and 65, except to deliver implicit intuitive intent to a future reader of the source code.
There are possibly hundreds of simple aliases such as atom/number, int/integer/bool (whereas boolean differs in having stricter validation), true/True/TRUE, get_file_base/filebase, K_ANY/KEY_CB, and so on.
There are a handful of (imo near-pointless) routines added for compatability with legacy Euphoria code, such as `head(s,n)` [===`s[1..n]`], `s = remove(s,i,j)` [===`s[i..j]=""`].
The inline assembler supports most standard intel instructions, so you have all the usual overlaps such as xor reg,reg and mov reg,0.
Not only is the compiler smart enough to suppress code generation for if false then and the like, it will also do the same for (say) if integer(x) then when it can determine that at compile-time via constant/type propagation, and issue proper warnings for "if integer(x) then ... elsif integer(x) then" and the like.
Of course "x = x + 3" and "x += 3" are completely identical.
More surprisingly perhaps, except when "fallthrough" or "with jump_table" is explicitly used, there is very little difference internally between a switch statement and an if construct, though of course the latter can express tests on multiple variables, which switch cannot.
While "s = append(s,x)" and "s &= x" are the same when x is an atom, they're not when x is string/sequence.
One genuinely redundant feature which has since been redacted was "{a, b, c} @= x", where the "@=" was meant to stand for "all become equal to". Technically it just about worked when x was a literal integer, but was badly broken in almost every other sense, and from the 0 bug reports clearly had never been used in the real world.

with javascript_semantics
integer i = 3
object i2 = 3 // same apart from error reporting
int i_too = 3 // int is just an alias of integer
-- six different ways to set i to 3:
i = 0b11
i = 0(2)11
i = 0(36)3
i = #3
i = 0x3
i = '\#03'

i = i+3
i += 3

sequence s = {1,2,3,4,5}
-- four ways to print the first two
?head(s,2)
?s[1..2]
pp(s[1..2])
printf(1,"%v\n",{s[1..2]})
-- two ways to append a 3
?{1,2}&3
?append({1,2},3) -- (nb same only when appending a single number)

if true then
    // do something
else
    printf(1,"Never called\n")
end if
 
for i=1 to 0 do
    printf(1,"Never called\n")
end for
 
while false do
    printf(1,"Never called\n")
end while
 
printf(1,"") -- (On Windows, will create a console if one not already attached)
 
printf(1,"Working OK.\n")

(In fact, if you run "p -d test.exw" on the above, if true .. end while only emits a single instruction, mov i,3 at the start of the for loop, and no other instructions at all for those thirteen lines.)
(Also, for the above and this by inspecting the list.asm file created, you would be able to see that it doesn't bother adding 3 to i, but instead simply sets it to 6 then 9.)

Output:
{1,2}
{1,2}
{1,2}
{1,2}
{1,2,3}
{1,2,3}
Working OK.

Quackery

Several words in Quackery just put a number on the stack and could be replaced by literals. (Literal numbers are words in Quackery; their behaviour is to put their value on the stack.) For example, true and false which put 1 and 0 on the stack respectively and are arguably redundant, as Quackery programmers know, or really should know, these values.

However, they are not useless, unless code legibility is regarded as a useless criterion. It is not.

A second way of looking at this task is to understand that a Quackery program is a sequence of words (one or more printable characters) separated by whitespace, and that there are no invalid programs, but there are a great many essentially useless words; they are useless because they are not yet known to Quackery.

Your cat could write a valid, but probably useless, Quackery program by walking across the keyboard. Say it types fvefbbfibiu, and you pass this string to the Quackery compiler, build. build will cheerfully return a perfectly valid Quackery program. Executing that program with do will reveal that it prints a string to the console, and that string is Unknown word: fvefbbfibiu, (assuming that you have not previously defined the word fvefbbfibiu.)

Raku

I disagree with the whole premise. There are pretty darn few instructions that are completely useless in any language unless you are using them in ways not intended, or are deliberately structuring them to be useless; and most of the existing examples point that out.

.oO( This chainsaw is crap at driving screws in... ) Well duh.

.oO( I've multiplied this numeric value by 1 millions of times and it still hasn't changed! ) Thanks for your contribution, Captain Oblivious.

Redundant instructions / operations on the other hand... Syntactically different operations that can be used to achieve the same result abound in higher level languages. In general they are intended to be used in slightly different circumstances, or are just syntactic sugar to condense a multi-step operation down to a more compact representation. Raku is just full of syntactic sugar operations.

Programming languages aren't for computers, they are for people. If they were for computers, we would be programming in binary code. Having an expressive language that helps the programmer transform his thoughts into code leads to "redundancies" due to allowing for shades of meaning that make sense to people though may be insignificant to computers.

Some examples: Say you have a variable $x that holds an integer, and you want to add 1 to it.

my $x = 1;

$x = $x + 1;  # classic
$x += 1;      # classic abbreviated
++$x;         # pre-increment
$x++;         # post-increment
$x.=succ;     # method, find successor

Raku is by no means unique in that regard. Each one of those nominally accomplishes the same thing, though they go about it in slightly different ways, and are intended for slightly different purposes. Redundant on the face of it, but different reasons for each.

There may be different operations that essentially perform the same function that have been retained for historical compatibility and / or ease for crossover programmers. the for next construct really only exists in Raku for programmer convenience. Internally it is converted to a map operation. Programmers can use map directly, but if they come from a language that doesn't provide map, and aren't used to it, for next is a easy stepping stone.

for 1..10 { next if $_ %% 2; say '_' x $_ };  # for next
map { next if $_ %% 2; say '_' x $_ }, 1..10; # equivalent map

Syntactic sugar (typically) replaces some longer expression with a shorter, more easily typed one. Raku abounds with them.

my @a1 = Q:w[one two three]; # list of strings using the Q sublanguage
my @a2 = <one two three>;    # syntactic sugar for the same operation

say (1,2,3,4,5,6,7).reduce(&infix:<*>); # multiply all of the items in a list together 
say [*] (1,2,3,4,5,6,7);                # same operation, sweeter syntax

Wren

There are no language features or standard library methods in Wren which are completely redundant either by design or due to subsequent developments. However, it's not difficult to think of instances where some of them can be used in a redundant way as in the following script.

For good measure I've also included something which looks useless but isn't in fact.

var uselessFunc = Fn.new { |uselessParam|  // required but never used
    if (true) {
        // do something
    } else {
        System.print("Never called")
    }

    for (e in []) {
        System.print("Never called")
    }

    while (false) {
        System.print("Never called")
    }

    System.write("")  // no visible effect

    return // redundant as function would return 'naturally' anyway
}

class NotCompletelyUseless {
    /*
       On the face of it this class is useless because:
       (1) it has no methods
       (2) although it inherits from Object, static methods are not inherited

       However, it's not in fact completely useless because:
       (3) a Class object is still created and accessible
       (4) it can be used as an abstract base class for other classes
    */
}

uselessFunc.call(0)
System.print(NotCompletelyUseless) // prints the string representation of the Class object
Output:
NotCompletelyUseless

x86 Assembly

Originally, LOOP label was a one-line version of DEC ECX JNZ label, but even Intel now recommends to use the latter over the former, due to LOOP taking longer to execute than DEC ECX JNZ on the 486 and beyond. Most compilers don't use LOOP anymore either. An explanation can be found here.

Z80 Assembly

CP 0 is nearly useless, but for a different reason than on 6502 Assembly. Unlike the 6502, loading a value into the Z80's main registers never updates the flags*. However, it's much better to use OR A, which bitwise ORs A with itself, setting the zero and carry flags the same way that CP 0 would, but takes one fewer byte and 3 fewer CPU states. (Keep in mind that the compare instruction can only compare the accumulator A with something else.) Comparing to zero does set some flags differently, which can matter for a DAA, but these situations are few and far between.

(*The only exception is the I and R registers, which when loaded into A will set the P/V flag when interrupts are enabled.)

RES #,A and SET #,A are one CPU state slower than an AND/OR with the appropriate bit mask. Bit masks allow you to set or clear multiple bits in one go, as well as have a variable operand, which the BIT/SET/RES instructions cannot do without self-modifying code.

It should be pointed out that bit masks only really work with A, not other registers. For other registers, SET and RES are perfectly usable.

Compare the following code snippets, which are functionally identical but the latter is half the size and more than double the speed:

SET 7,A
SET 6,A
RES 5,A
RES 4,A
;TOTAL 8 BYTES, 32 CPU STATES

OR %11000000
AND %11001111
;TOTAL 4 BYTES, 14 CPU STATES