racket

What is the meaning of '?' in the Racket docs?


Example:

(number? v) → boolean?

  v : any/c

I understand the '?' behind 'number' but the second '?', behind 'boolean' irritates me. Does it mean that it maybe returns a boolean, and maybe not?

To me this reads as: is_number::function returns is_boolean::function and not is_number::function returns bool::bool.

Solution

As Jérôme explained, it reads as:

is_number(v) returns b where is_boolean(b) == True

Update 2022

Section 2 in the Racket reference explains the formal syntax used in the documentation. Section 2.3 explains the ?.

Quote (I added the links):

(char->integer char) → exact-integer?
char : char?

Each metavariable is described with a contract. (...) The metavariable char has the contract char?. This contract specifies that any argument char that answers true to the char? predicate is valid. The documented function may or may not actually check this property, but the contract signals the intent of the implementer.


Solution

  • boolean? is a predicate. It's a function that has (by convention) a question mark at the end to show it can be used to check for the type of a value and return a boolean, like so:

    > (boolean? #f)
    #t
    > (boolean? "hello")
    #f
    

    By default Racket is dynamically typed, so in order to show type information in the documentation, predicates are used as a kind of type annotation.

    So basically, (number? v) → boolean? means "The function number? returns a value which, when passed to the predicate boolean?, returns true".

    It becomes useful when you have more complex predicates:

    (pick-random-stuff bag?) → (listof (or/c toy? food? paperclip? aligator?))
    

    This function returns a list containing any amount of those different objects in any order.

    Notes

    It is considered a good practice to always name your predicates with a ? at the end.

    You might have noticed though that in my examples, listof and or/c don't have question marks. It's because they are not predicates themselves, but functions that build predicates.

    In most lisp languages, like Scheme, Racket, Clojure, or Common Lisp, a lot of symbols that have specific meanings in other languages are just valid identifiers. ?, =, -, ->, + are all allowed inside variable and function names.