iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🎾

Comparison Operators in Racket: A Practical Guide to Numeric and String Types

に公開

Introduction

This article explains comparison operators in the Racket language.
Racket is a functional language[1] that follows the lineage of LISP[2] and Scheme, and it comes with various built-in data types.
There are comparison operators tailored to each data type, and using them effectively requires some experience.

In this article, I will introduce comparison operators for representative types: numeric and string types. I hope this provides some insight into the characteristics of the Racket language.

What is Racket?

Features of Racket

Racket is a general-purpose programming language that supports both functional and object-oriented programming paradigms. The features of Racket are as follows:

  • Supports both functional and object-oriented programming
  • Simple and easy-to-understand syntax
  • Supports macros, allowing for feature extensions
  • Rich standard library providing various practical tools

Comparison Operators

In Racket, there are comparison operators for each data type. I will introduce numeric and string types, which are representative data types, using code examples.

Numeric Comparison Operators

In Racket, operations combining three data types—integers, rational numbers, and real numbers—are possible. This section explains the numeric comparison operators in the Racket language.

List of Numeric Comparison Operators

The numeric comparison operators are shown in the table below.

Operator Description
< Less than
> Greater than
<= Less than or equal to
>= Greater than or equal to
= Equal to

Important Note

  • Racket does not have an operator to represent "not equal to".

Examples of Numeric Comparison Functions

Here is an example of a function that compares two numbers.

compare-numbers.rkt
(define (compare-numbers a b)
   (cond
      [(< a b) "a is less than b"]
      [(> a b) "a is greater than b"]
      [(= a b) "a and b are equal"]))

In the example above, a function named compare-numbers is defined to compare two numeric values, a and b. It uses cond to perform the numeric comparison and returns a string based on the result.

Function usage example:

> (compare-numbers 4 5)
"a is less than b"

> (compare-numbers 3/2 1)
"a is greater than b"

> (compare-numbers 3/2 "abc")
<: contract violation
  expected: real?
  given: "abc"

As seen in the last example, passing a non-numeric data type causes a "contract violation" error (type mismatch). To avoid this, you need to use the number? function to check if the data is a numeric type and filter out non-numeric values.

The following example shows a function that uses number? to compare values while handling non-numeric types.

compare-values.rkt
(define (compare-values a b)
   (cond
      [(and (number? a) (number? b))
            (cond
               [(< a b) "a is less than b"]
               [(> a b) "a is greater than b"]
               [(= a b) "a and b are equal"])]
      [else "Not a number"]))

Important Note

  • If the arguments are not of a numeric type, "Not a number" is displayed.

Function usage example:

> (compare-values 1 2)
"a is less than b"

> (compare-values 2 2)
"a and b are equal" is displayed

> (compare-values "a" "b")
"Not a number"

Comparison Across Data Types

In Racket, you can compare numbers of different data types, such as integers and rational numbers, or real numbers and rational numbers.
For example:

> (> 1 1.5)
#f
> (> 1.5 2/3)
#t
> (> 1.5 5/3)
#f

Comparison of Multiple Numeric Values

You can also compare multiple numeric values at once.
For example:

> (> 3 2)
#t
> (> 3 2 2)
#f
> (> 3 2 1)
#t

When multiple numeric values are provided, Racket compares them in pairs and returns the result of their logical "and". In the case of (> 3 2 2), it returns #f because the result of (> 2 2) is #f.

String Comparison Operators

In Racket, strings are represented using the Unicode standard. Unicode is used for string comparisons.
This section explains the string comparison operators in the Racket language.

List of String Comparison Operators

The string comparison operators are shown in the table below.

Operator Description
string=? Equal to
string<? Less than (alphabetical order)
string>? Greater than (alphabetical order)
string<=? Less than or equal to (alphabetical order)
string>=? Greater than or equal to (alphabetical order)
string-ci=? Case-insensitive equal to
string-ci<? Case-insensitive less than
string-ci>? Case-insensitive greater than
string-ci<=? Case-insensitive less than or equal to
string-ci>=? Case-insensitive greater than or equal to

Examples of usage are shown below.

(string<? "apple" "banana") ; #t
(string>? "apple" "banana") ; #f
(string<=? "apple" "banana") ; #t
(string>=? "apple" "banana") ; #f
(string=? "apple" "orange") ; #f
(string-ci=? "apple" "Apple") ; #t
(string-ci<? "apple" "Banana") ; #t
(string-ci>? "apple" "Banana") ; #f
(string-ci<=? "apple" "Banana") ; #t
(string-ci>=? "apple" "Banana") ; #f

Operators ending with "-ci", such as string-ci=?, perform comparisons without distinguishing between uppercase and lowercase letters. Whether to treat English uppercase and lowercase letters as the same character should be decided based on the specific situation.

Comparison of Japanese and Other Languages

Since Racket uses Unicode for string representation, comparisons of non-alphanumeric characters such as Japanese are also possible.
An example of string comparison in Japanese is:

> (string<? "こんにちは" "こんばんは")
#t

Comparison of Multiple Strings

Comparison of multiple strings is also possible.
Examples of multiple comparisons are:

> (string>? "abc" "abb" "ab")
#t

> (string>? "abc" "abb" "abb")
#f

Equality Comparison Operators

In Racket, various operators are provided to compare whether two pieces of data are "equivalent."
The representative operators and their features are introduced below.

Operator Description Example
= Two numeric values are equal (= 2 2)#t
eq? True (#t) when two pieces of data refer to the same object (eq? 'a 'a)#t
eqv? True (#t) when the values of two data (objects) are equal (eqv? "abc" "abc")#t
equal? Recursively compares all elements of compound data types[3] (equal? '(a b c) '(a b c))#t

Important Notes

  • = : Results in an error if the data type is anything other than numeric.
  • eq? : The result depends on the Racket implementation.
  • equal? : Used for compound data types[3:1] that aggregate multiple data types, such as list and vector types.

The = Operator

Usage: (= a b)

The = operator compares whether two numeric values are equal. Comparing non-numeric types results in an error.
Below are examples of Racket programs using the = operator.

> (= 1 2)
#f
> (= 2 2)
"t
> (= 2 2.0 )  ; Comparison of integer and real
#t
> (= 1 4/4)   ; Comparison of integer and rational
#t
> (= "apple" "apple") ; Error
=: contract violation
  expected: number?
  given: "apple"

The eq? Operator

Usage: (eq? a b)

The eq? operator returns true (#t) if two pieces of data refer to the same object.
Below are examples of Racket programs using the eq? operator.

> (define a 12)
> (define b 12)
> (define c b)
> (eq? a b)
#t
> (eq? b c)
#t
> (eq? 'a 'a)
#t
> (eq? "apple" "banana")
#f

The eqv? Operator

Usage: (eqv? a b)

The eqv? operator returns true (#t) if the values of two data types are equal.
Below are examples of Racket programs using the eqv? operator.

> (define a 12)
> (define b 12)
> (eqv? a b)
#t
> (eqv? 'a 'a)
#t
> (eqv? "apple" "banana")
#f
>(eqv? '(a b c) '(a b c))
#f
>(eqv? '(a b c) '(a b d))
#f

Important Note

  • Lists result in false (#f) because different objects are generated.

The equal? Operator

Usage: (equal? a b)

The equal? operator recursively compares all contents of the passed data type to see if they are equal.
For data types consisting of multiple elements, such as list and vector types, it checks whether each element is equal.
Below are examples of Racket programs using the equal? operator.

> (define a 12)
> (define b 12)
> (equal? a b)
#t
> (equal? 'a 'a)
#t
> (equal? "apple" "banana")
#f
>(equal? '(a b c) '(a b c))
#t
>(equal? '(a b c) '(a b d))
#f

Unlike eqv?, equal? also compares the objects within the list, so (equal? '(a b c) '(a b c)) returns true (#t).

Special Comparison Operators

There are also operators that check whether data has a special value. Here, I will introduce representative ones and their characteristics.

Operator Description Example
zero? Whether a numeric value is 0 (zero? 0)#t
null? Whether a list is an empty list (null? '())#t
empty? Whether an input list is empty (empty? '())#t
void? Whether it is of the void type (void? (set! a 3))#t

Important Notes

  • (zero? <DATA>): Results in an error if <DATA> is not a numeric type.
  • (null? <DATA>): A function that checks if the argument is '() (empty list). Returns #f for non-list types.
  • (empty? <DATA>): A function that checks if the argument list is empty ('()). Returns #f for non-list types.
  • (void? <DATA>): A function to check if the argument is of the void type.

null? and empty? are functions commonly used with list types. In particular, null? is frequently used for end-of-list checks.

zero?

Usage: (zero? num)

The zero? operator checks whether a numeric value is 0.

zero?
> (zero? 0)
#t
> (zero? 0.0)
#t
> (zero? -0)
#t
> (zero? 0.1)
#f
> (zero? "abc")  ; Error
zero?: contract violation
  expected: number?
  given: "abc"

null?

Usage: (null? lst)

The null? operator checks whether the given list is an empty list ('()).

null?
> (null? '())
#t
> (null? null)
#t
> (null? '(1 2))
#f
> (null? "abc")
#f

empty? : Checking if a list is empty

Usage: (empty? lst)

The empty? operator checks whether the given list is empty.

empty?
> (empty? '())
#t
> (empty null)
#t
> (empty? '(1 2))
#f
> (empty? "abc")
#f

void? : Checking if the argument is of the void type

Usage: (void? obj)

The void? operator checks whether the argument is of the void type.

null?
> (void? (display ""))
#t
> (void? 1)
#f
> (void? (+ 1 2))
#f

Conclusion

In this article, I have introduced comparison operators in Racket. Using comparison operations in conditional branches and loops is a fundamental operation in programming.

By utilizing the operators and functions introduced here, you can create practical Racket programs. As your programming becomes more advanced, comparison operations will become more complex, so let's continue learning to use comparison operations appropriately in functional languages.

Happy Hacking!

References

Books

Web

脚注
  1. Functional language: A programming paradigm that views programs as a collection of mathematical functions. By eliminating side effects, it enables program reliability and concurrent processing. ↩︎

  2. LISP: Short for LISt Processing, a programming language capable of manipulating lists. ↩︎

  3. Compound data type: A data type that aggregates multiple pieces of data, such as list and vector types. ↩︎ ↩︎

GitHubで編集を提案

Discussion