But consider car
. It takes a pointer to a cons cell — roughly, a structure containing a “car” pointer and a “cdr” pointer — and it returns the “car” pointer. In order to look that up, it has to dereference the pointer to the cons cell.
So some functions (like car
) do dereference the locations (pointers)? So read-only dereferencing would be required here, right? Or is this not considered dereferencing?
If this ever gets to some library, the behaviour must be described in the docs, as there are several possible definitions of flmod
and none is really standard: https://en.wikipedia.org/wiki/Modulo_operation#In_programming_languages
I decided to put it on StackOverflow instead. https://stackoverflow.com/questions/65411276/how-to-compute-a-floating-point-modulo-in-racket-flmod
is there a Mutable-Setof
in Typed Racket? if not, how do I denote a mutable set?
also how do I add type annotations for a function defined with varargs (e.g. (define (fn . args) ...)
)?
Hmm, I’m not sure how to answer that. This allegory I’ve been describing, where all Racket variables are like C variables of type (racket_value *)
, is something I’m bringing up mainly to help bridge to your mental model so that I can discuss the “pass by reference or not” question. On the Racket side of this allegory, since everything has the same type, there’s usually no reason (apart from performance) to make a distinction between between pointers and non-pointers, and likewise no reason to say that any pointer is being dereferenced.
Racket values aren’t all read-only. A lot of Racket values are immutable (like integers), and a lot of them are mutable (like ports). A lot of Racket data structures exist in both mutable and immutable variations (like strings, hash tables, vectors, cons cells, and structs).
However, in this every-variable-has-type-(racket_value *)
allegory, doing arbitrary mutation at that particular address might allow you to change a Racket value from one type to another (e.g. perhaps change an integer into a port), and that’s not an operation that occurs in safe Racket programs. Take mcons
mutable cons cells, for instance. The ways to mutate them are set-mcar!
(which doesn’t touch the type tag or the mcdr
) and set-mcdr!
(which doesn’t touch the type tag or the mcar
). While these do overwrite the data of a mutable cons cell (meaning the (racket_value *)
isn’t a read-only pointer), neither one overwrites the type tag; Racket offers no safe way to mutate a mutable cons cell so that it becomes an integer or a port.
@hazel I recommend type-annotating functions using the Haskell-style syntax: (: fn (A * -> B))
(define (fn . args) ...)
If you need fancier types, see the docs for ->
and ->*
.