How do I access the value of a node in racket? - racket

I have defined the following node struct:
(struct list-node
(val next) #:mutable #:transparent)
When I create a list node (list-node 0 #f), however, I don't know how to access the val of this created node. How do I do that?

The fields of something defined as (struct <name> (<field-name> ...) ...) are accessed with <name>-<field-name> and (if mutable) set with set-<name>-<field-name>!. There may be options that override these defaults but I don't know them.
So for
(struct list-node
(val next) #:mutable #:transparent)
Then list-node-val gets the val of a list-node and set-list-node-val! sets it:
(let ([n (list-node 3 #f)])
(set-list-node-val! n (+ 1 (list-node-val n)))
(set-list-node-next! n (list-node 6 n))
n)
Will return a list-node with val 6, and next being another list-node whose next is the original list-node.

Related

Generate stream in racket

I'm trying to generate a stream in racket that contains a sequence of 1 or 2 element lists.
It should start with the number one in a list and every subsequent element of the stream is incremented by one with the added requirement of even numbers should be duplicated in the list.
For example: ((1)(2 2)(3)(4 4)(5)(6 6))
How would I be able to do that?
It's a 2-step process:
Create stream like 1, 2, 3, 4. ... using in-range or in-naturals
Map over each element to transform them into lists with stream-map
This code snippet shows a way to create infinite as well as bounded "even-odd" lazy streams:
#lang racket
; (-> Nat (U (list Nat Nat) (list Nat)))
; a pair of `nat` if nat is even, singleton list otherwise
(define (nat->stream-elem nat)
(if (even? nat) (list nat nat) (list nat)))
; (->* () (Nat) (stream-of (U (list Nat Nat) (list Nat))))
; a stream with `total`, infinite stream if no arg provided
(define (even-odd-stream [total false])
(stream-map nat->stream-elem (if total (in-range 1 (+ total 1)) (in-naturals 1))))
; (-> Nat Void)
; displays first `to-display` elements from `stream`
(define (display-stream to-display stream)
(for ([i to-display] [e stream])
(displayln e)))
; Displays all 6 elements of a 6-element even-odd-stream
(display-stream 6 (even-odd-stream 6))
(displayln "- - -")
; Displays first 10 elements of an infinite even-odd-stream
(display-stream 10 (even-odd-stream))
Write a function, sc, say, which takes one argument, n say. It should return:
if its argument is even (stream-cons (list n n) (sc (+ n 1)));
if its argument is odd (stream-cons (list n) (sc (+ n 1))).
(sc 1) is the stream you want.

Understanding a macro

As I understand the macro written below; The macro takes 3 arguments and produces a struct with a constructor which accepts 3 arguments. I can guess that the line immediately following the macro definition creates a struct which looks like:
(struct x (+ y x))
I am lost in understanding how the two lines which follow that work. It appears that y is bound to an x struct, but isn't it calling the constructor with one too many arguments?
(define-syntax binary-search
(syntax-rules ()
[(binary-search (node left right))
(struct left (node right x))]))
(binary-search (+ x y))
(define y (x 1 2 3))
(+ (x-+ y) (x-x y))
I won't be a bother and ask how the last line works, hopefully clarification on the y variable will lead me to the given answer of 4.
What's confusing here is that a field name can be the same as the struct name.
Consider this example:
#lang racket
(struct foo (foo) #:transparent)
(foo 42) ; => (foo 32)
(foo-foo (foo 42)) ; => 32
So (binary-search (+ x y)) results in:
(struct x (+ y x))
which defines an x struct that has a named also named x.
The line
(define y (x 1 2 3))
makes an x-struct where:
the + field stores 1,
the y field stores 2,
the x field stores 3.
Now (x-+ y) gets the + field of y, which is 1
and (x-x y) gets the x field of y which is 3.
This means that (+ (x-+ y) (x-x y)) evaluates to 4.

Unique identifier for Racket objects?

Is there a way to get a unique identifier for an object in Racket? For instance, when we use Racket's eq? operator to check whether two variables refer to the same object, what identifier is it using to achieve this comparison?
I'm looking for something like python's id function or Ruby's object_id method, in other words, some function id such that (= (id obj) (id obj2)) means that (eq? obj obj2) is true.
Some relevant docs:
Object Identity and Comparisons
Variables and Locations
Is eq-hash-code what you want?
> (define l1 '(1))
> (define l2 '(1))
> (eq? l1 l2)
#f
> (eq-hash-code l1)
9408
> (eq-hash-code l2)
9412
There's a way to get a C pointer of an object via ffi/unsafe, with the obvious caveat that it's UNSAFE.
;; from https://rosettacode.org/wiki/Address_of_a_variable#Racket
(require ffi/unsafe)
(define (madness v) ; i'm so sorry
(cast v _racket _gcpointer))
To use it:
(define a (list 1 2))
(define b (list 1 2))
(printf "a and b have different address: ~a ~a\n"
(equal? (madness a) (madness b))
(eq? a b))
(printf "a and a have the same address: ~a ~a\n"
(equal? (madness a) (madness a))
(eq? a a))
(printf "1 and 1 have the same address: ~a ~a\n"
(equal? (madness 1) (madness 1))
(eq? 1 1))
Though the pointer is not a number or an identifier. It's an opaque object... So in a sense, this is kinda useless. You could have used the real objects with eq? instead.
I also don't know any guarantee of this method. In particular, I don't know if the pointer will be updated to its latest value when the copy GC copies objects.
Here is an implementation of such a function using a weak hash table.
Using a weak hash table ensures that objects are garbage collected correctly
even if we have given it an id.
#lang racket
(define ht (make-weak-hasheq))
(define next 0)
(define (get-id x)
(define id (hash-ref ht x #f))
(or id
(begin0
next
(hash-set! ht x next)
(set! next (+ next 1)))))
(get-id 'a)
(get-id 'b)
(get-id 'a)
Note that Sylwester's advice is sound. The standard is to store the value directly.
You most likely won't find an identity, but the object itself is only eq? with itself and nothing else. eq? basically compares the address location of the values. So if you want an id you can just store the whole object at that place and it will be unique.
A location is a binding. Think of it as an address you cannot get and an address which has an address to a object. Eg. a binding ((lambda (a) a) 10) would store the address location of the object 10 in the first stack address and the code in the body just returns that same address. A location can change by set! but you'll never get the memory location of it.
It's common for lisp systems to store values in pointers. That means that some types and values doesn't really have an object at the address, but the address has a value and type encoded in it that the system knows. Typically small integers, chars, symbols and booleans can be pointer equal even though they are constructed at different times. eg. '(1 2 3) would only use 3 pairs and not any space for the values 1-3 and ().

What is the difference between a transparent and a prefab struct?

As the title implies, I don't understand the difference between using #:transparent and using #:prefab when defining a struct. The reference mentions that prefab involves some sort of global sharing.
What is the difference between them? In which situation should I use one over the other?
To make a structure type transparent, use the #:transparent keyword after the field-name sequence:
(struct posn (x y)
#:transparent)
> (posn 1 2)
(posn 1 2)
An instance of a transparent structure type prints like a call to the constructor, so that it shows the structures field values. A transparent structure type also allows reflective operations, such as struct? and struct-info, to be used on its instances.
Although a transparent structure type prints in a way that shows its content, the printed form of the structure cannot be used in an expression to get the structure back, unlike the printed form of a number, string, symbol, or list.
A prefab (“previously fabricated”) structure type is a built-in type that is known to the Racket printer and expression reader. Infinitely many such types exist, and they are indexed by name, field count, supertype, and other such details. The printed form of a prefab structure is similar to a vector, but it starts #s instead of just #, and the first element in the printed form is the prefab structure type’s name.
Lastly, I think you may need using #:transparent most of the time over #:prefab ,based on my experience I usually use #:transparent.
To extend the other answers and give some more examples for the second part of the question:
#lang racket
(struct A (x y))
(displayln (A 1 2)) ; => #<A>
(equal? (A 1 2) (A 1 2)) ; => #f
;(equal? (A 1 2) (read (open-input-string (~a (A 1 2))))) ; => ERR: bad syntax
(struct B (x y) #:transparent)
(displayln (B 3 4)) ; => #(struct:B 3 4)
(equal? (B 3 4) (B 3 4)) ; => #t
(equal? (B 3 4) (read (open-input-string (~a (B 3 4))))) ; => #f
(struct C (x y) #:prefab)
(displayln (C 5 6)) ; => #s(C 5 6)
(equal? (C 5 6) (C 5 6)) ; => #t
(equal? (C 5 6) (read (open-input-string (~a (C 5 6))))) ; => #t
Use opaque structs if you want to enforce the struct abstraction with no exceptions, i.e., the struct can only be created and inspected with the accessors.
Use transparent structs to give access to the printer and equal?.
Use prefab structs if you want to do serialization, e.g. when writing and reading from disk.
The racket guide probably has a more gentle introduction to prefab structs.
The biggest difference is that a transparent struct still requires the struct constructor to create one of them.
For example, given the following struct definition:
(struct foo (a b) #:prefab)
The following are two ways to create the exact same struct.
> (foo 1 2)
'#s(foo 1 2)
> #s(foo 1 2)
'#s(foo 1 2)
This means that any racket module can create a foo prefab struct, even without it being defined first. This makes it very useful if you want to put it in a macro, or send it to a separate instance of racket running on a different machine.
Generally, I would recommend going with #:transparent structs unless you need the full power of a #:prefab struct.
One other important detail not mentioned yet: transparent (and normal) structs are generative. This means if you define the same struct twice, values created with the first instance of the struct definition are not equal? to values created with the second definition. You can see this for yourself in a REPL session:
> (struct posn (x y) #:transparent)
> (define origin1 (posn 0 0))
> (struct posn (x y) #:transparent)
> (define origin2 (posn 0 0))
> (equal? origin1 origin2)
#f
Despite being the same definition and having the same content, the two instances are not equal?. Although the structs are transparent they are considered separate definitions for the reason Leif Anderson pointed out, just using #:transparent still requires that the only way to create the struct be with the constructor the struct form defines. Two definitions means two different constructors.
However, with prefab structures, that limitation goes away - you can create prefab structs yourself by just writing the reader form of them like #s(posn 0 0). There's no longer a reason to require all instances of the struct be created with its defined constructor, and thus no reason two different but identical struct definitions wouldn't recognize each other:
> (struct posn (x y) #:prefab)
> (define origin1 (posn 0 0))
> (struct posn (x y) #:prefab)
> (define origin2 (posn 0 0))
> (equal? origin1 origin2)
#t
> (equal? origin1 #s(posn 0 0))
#t
I am of the opinion that structs that represent just some raw data pooled together should be prefab to get free, easy, and safe serialization, structs that have restrictions on how they can be constructed should be transparent, and structs that should encapsulate some behavior and hide information should be neither transparent nor prefab. These are mere guidelines however, your mileage may vary.

Understanding objects with local state -- Scheme

i'm studying for my scheme final and objects with local state has always been a tough subject.
Here is a question from my final exam that i need help on.
(define (make-incrementer n)
(let ((old 0)
(new 0))
(lambda ()
(cond ((< new n)
(set! old new)
(set! new (+ new 1))
old)
(else
(set! old 0)
(set! new 1)
old)))))
(define a (make-incrementer 3))
(define b (make-incrementer 3))
(define c a)
; 1) (a)
; 2) (a)
why when a is called the second time it returns 1? I'm looking at the code and the n we give it is always 3. So wouldn't it always do the else case?
Welcome to the wonderful world of closures! This is a textbook example of how closures in Scheme work.
So make-counter returns a function that has 3 variables that it captures from it's enclosing environment: n, old, new. In this case, the starting environment looks something like
_name_|_value_
n | 3
old | 0
new | 1
On each invocation, it increments old and new and wraps them around if they're greater than n. Because it's using set!, this incrementing is mutating the variables in the lambda's environment, but since these variables are captured from the surrounding environment, they are changed for all future calls as well.
That's why you get different returns even with the same input.
If this seems like witchcraft, you can think of it like objects in more common languages:
Eg Python:
class Foo():
def __init__(self, n, m):
self.n = n
self.m = m
def count(self):
self.n += 1
if self.n == self.m:
self.n = 1
return self.n-1
f = Foo(0, 2)
f.count() # 1
f.count() # 0
This is the same basic idea except here we're being a bit more explicit about where the environment is coming from, self. In Scheme, we mimic this with the lambda capturing the surrounding variables.
For more, check out SICP
Here are some examples, that might help with the concept of capturing state:
(define (always x)
(lambda rest x))
(define always-true (always #t))
(always-true #f)
-> #t
(define (add-n n)
(lambda (m)
(+ n m)))
(define add-1 (add-n 1))
(add-1 10)
-> 11
(define (complement predicate)
(lambda (x)
(not (predicate x)))
(define not-positive? (complement positive?))
(not-positive? -1)
-> #t
Next is an example where the captured state, in this case l, is mutated. This is similar to your case where new and old are captures and modified.
(define (nexting l)
(lambda ()
(if (null? l)
'()
(let ((answer (car l)))
(set! l (cdr l))
answer))))
(define next-user (nexting '(Alice Bob David)))
(next-user)
-> Alice
(next-user)
-> Bob
(next-user)
-> David
(next-user)
'()