Dear all,

Just imagine, suppose we have two traits `spots-trait` and `stripes-trait`,
they are developed independently.

These two traits depend on a "private" method `helper` respectively.

See following code:

```
(define spots-trait
  (trait
   (define/public (helper)
     (println "spots-trait helper"))
   (define/public (eat/spots)
     (println "spots-trait eat/spots")
     (helper))
   ))

(define stripes-trait
  (trait
   (define/public (helper)
     (println "stripes-trait helper"))
   (define/public (eat/stripes)
     (println "stripes-trait eat/spots")
     (helper))
   ))
```

Now I want to define the 3rd trait (called `spots+stripes-trait`),
something like:

```
(define spots+stripes-trait
  (trait-sum spots-trait stripes-trait))
```

But this is impossible because there is a name colliding (the`helper`
method).

One workaround to this problem is "renaming":

```
(define spots+stripes-trait
  (trait-sum
   (trait-rename spots-trait helper helper/spots)
   (trait-rename stripes-trait helper helper/stripes)))
```

This works.

But is this a good way? (It looks not very "hygienic")

Note that the `helper` is just a "private" method, it should not be visible
to its user.

PS: It seems that Racket does not support private members for traits.
Although I don't think "private members" is a good idea because private
members are not friendly to unit-testing.

An alternative way is moving the private `helper` method to a different
trait, splitting the original responsibilities across multiple traits
leading to simpler, better designs.

See following code:

```
(define spots-helper-trait
  (trait
   (define/public (helper)
     (println "spots-helper-trait helper"))
   ))

(define spots-core-trait
  (trait
   (inherit helper)
   (define/public (eat/spots)
     (println "spots-core-trait eat/spots")
     (helper))
   ))

(define stripes-helper-trait
  (trait
   (define/public (helper)
     (println "stripes-trait helper"))
   ))

(define stripes-core-trait
  (trait
   (inherit helper)
   (define/public (eat/stripes)
     (println "stripes-core-trait eat/spots")
     (helper))
   ))
```

Now I can redefine `spots-trait` and `stripes-trait`.

My attempt is `trait-sum` the `spots-core-trait` and `spots-helper-trait`
first, and then "hide" the `helper`, something like:

```
(define spots-trait
  (trait-hide ;; <-- attempt to hide `helper` method (Not real Racket)
   (trait-sum spots-core-trait spots-helper-trait)
   helper))

(define stripes-trait
  (trait-hide ;; <-- attempt to hide `helper` method (Not real Racket)
   (trait-sum stripes-core-trait stripes-helper-trait)
   helper))

(define spots+stripes-trait
  (trait-sum spots-trait stripes-trait))
```

Is this possible in Racket?

The advantage of "hiding" is that

1. The `spots-trait` now only exposes its interface `eat/spots `, we can
easily reuse it in other traits without worrying about name colliding (the
name `helper` is very commonly used, imo) .

2. Compared with the "renaming" solution, "hiding" looks more "hygienic",
because it can avoid further name colliding.

PS: I admit this example may be a bit weird, but you can think of "spots"
and "stripes" as some sort of service traits.

Thanks.

Best regards,
Siyuan Chen

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAHWTsY%3DBCOBXc%2BL9JkR%2BCnS2htKadRnrkpx4w6oUMS5OhdOEtw%40mail.gmail.com.

Reply via email to