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 [email protected].
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