# Dot notation for object field access and method calls - and bracket notation for indexing

**URL:** <https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227>\
**Category:** Show & Tell\
**Created:** [August 12, 2022, 1:39pm UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227 "2022-08-12T13:39:10Z")\
**Posts on this page:** 5\
**Page:** 2

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [August 30, 2022, 8:57am UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227/21 "2022-08-30T08:57:10Z")

</div>

> This issue extends to Racket's other data structures as well. Only lists let you write "non-prefixed" functions. So you can call `length` on a list, but you have to call `vector-length` on a vector, same with `vector-map` and `vector-set!` , etc.

The dot mechanism in sketching actually allows you to add "dot fields" and "dot methods" to structs.  
I am not sure it is a good idea to do so - so I haven't advertised or documented it.

Anyways, take a look at line 615 of "dot-method.rkt" and below.

The line

```
(add-predicate! 'vector vector?)

```

adds the new "type" vector to the dispatcher.

The line  
(add-fields! 'vector '(ref length x y z) )  
adds the fields ref, length, x, y and z to the dispatcher.  
In a program one can write:

```
v.length and v.x

```

The lines

```scheme
(add-method! 'vector 'length vector-length)
(add-method! 'vector 'ref vector-ref*)
(add-method! 'vector 'list vector->list)
(add-method! 'vector 'fill! vector-fill!)
(add-method! 'vector 'values vector->values)

```

adds methods.

You can now write `(v.list)` for `(vector->list v)` etc.

The problem is of course that `(v.list)` will be slower than `(vector->list v)`,  
but you will have to benchmark it to see how much.

> <https://github.com/soegaard/sketching/blob/main/sketching-lib/sketching/dot-method.rkt#L631>

---

<div class="post-metadata">

**Author:** ![alexh](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/alexh/32/315_2.png) [@alexh](https://racket.discourse.group/u/alexh)\
**Post date:** [August 30, 2022, 12:26pm UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227/22 "2022-08-30T12:26:37Z")

</div>

> [@hasn0life](#):
>
> Only lists let you write "non-prefixed" functions. So you can call `length` on a list, but you have to call `vector-length` on a vector, same with `vector-map` and `vector-set!`, etc.

Perhaps you could use the functions from `racket/sequence`, for example `sequence-length` works for strings, lists, vectors and many other collection types. `sequence-length` is a bit long to type, but you could always import a shorter version:

```scheme
#lang racket
(require
  racket/require
  (filtered-in
   (lambda (name)
     (and (regexp-match #rx"^sequence-" name)
          (regexp-replace #rx"^sequence-" name "s")))
   racket/sequence))

;; all "sequence-" functions are renamed to start with just "s"
(slength "hello") ;; 5
(slength (vector 1 2 3)) ;; 3
(slength '(a b c d)) ;; 4
(sref "hello" 1) ;; #\e
(sref (vector 1 2 3) 1) ;; 2
(sref '(a b c d) 1) ;; b

```

Alex.

---

<div class="post-metadata">

**Author:** ![hasn0life](https://avatars.discourse-cdn.com/v4/letter/h/a5b964/32.png) [@hasn0life](https://racket.discourse.group/u/hasn0life)\
**Post date:** [August 31, 2022, 7:14am UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227/23 "2022-08-31T07:14:57Z")

</div>

@soegaard That sounds pretty awesome actually. I agree that performance may be an issue with all these syntaxes that do runtime lookups, but the success of python and ruby (and clojure?) shows that it could be a worthwhile tradeoff for programmer comfort. I think its worth experimenting with.

@alexh I've looked at sequences before and thought they only worked with the `for` loops for some reason, I didn't realize you could use them standalone. But also if I'm gonna write `sequence-something` I might as well write the type, so this shortening concept is an improvement.

Perhaps I should take these ideas and try making languages with them at this rate to see how worthwhile they are in practice. 😮 I'll have to find some free time to study all of this more in depth though. Thanks everyone.

Also I should first use Super more extensively and see if it does enough since @soegaard probably considered many of these tradeoffs already when he made it.

---

<div class="post-metadata">

**Author:** ![Laurent.O](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/laurent.o/32/18_2.png) [@Laurent.O](https://racket.discourse.group/u/Laurent.O)\
**Post date:** [August 31, 2022, 2:28pm UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227/24 "2022-08-31T14:28:59Z")

</div>

Still work in progress, but just recently I've added support for mutation in dot-notation in [`bazaar/struct`](https://github.com/Metaxal/bazaar/blob/master/struct.rkt#L174).  
It requires some manual work though (which could probably be eased with a smarter constructor), but allows for selecting fields:

```scheme
#lang racket
(require bazaar/struct)

(struct person ([name #:mutable] [address #:mutable] phone))

(define person1 (person "bob" "there" "007"))

;;; With dot notation

(define-with-struct.id person1 person (name phone))
person1.name ; bob
(set! person1.name "alice")
person1.name ; alice
(person-name person1) ; alice

;;; Without dot notation

(define-with-struct person1 person (name [address place])) 
name ; alice
(set! name "bob")
name ; bob
place ; there
(set! place "nowhere")
(person-address person1) ; nowhere

```

Right now I'm likely the only user of bazaar/struct, but if there is some interest I can extract it to a documented and tested package.

Inheritance is not yet supported, but I'd like it to be.

---

<div class="post-metadata">

**Author:** ![greghendershott](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/greghendershott/32/98_2.png) [@greghendershott](https://racket.discourse.group/u/greghendershott)\
**Post date:** [August 31, 2022, 3:43pm UTC](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227/25 "2022-08-31T15:43:02Z")

</div>

> ```scheme
> (.name bella)
> 
> ```

I think that Clojure notation is for Java interop?

Generally (IIRC) Clojure prefers hash-tables (which it calls "maps"). To do look-ups you can apply a hash-table to its key or vice versa: e.g. both `(:some-key some-map)` and `(some-map :some-key)` work.

If you like that style, you can do something similar in Racket (albeit using symbol keys like `'some-key`) by redefining `#%app`; [here's a toy example](https://docs.racket-lang.org/rackjure/index.html#%28part._dict-app%29).

* * *

Structs and hash-tables are apples and oranges; each has pros and cons. Structs are faster, smaller, and stricter. Whether you consider "stricter" a bug or a feature, for a given purpose, tends to drive the preference, I think?

Certainly there are applications where functions pass around hash-tables, ignoring or preserving mappings they don't know or care about, and adding or updating others --- and that seems to be an advantage. Whereas for other applications that would seem way too "ad hoc". Probably the answer varies for things closer to the outer edge of an app where it interacts with the rest of the world.

[Previous page](https://racket.discourse.group/t/dot-notation-for-object-field-access-and-method-calls-and-bracket-notation-for-indexing/1227.md?page=1)
