A trait is applied with a verb, here is. That verb appears in the routine name that handles the trait, here trait_mod:<is>. The arguments to that handler are the object on which the trait is applied, and the name of the trait (here cached) as a named argument.

Note that a production grade is cached would need to handle multiple arguments, and maybe things like limiting the cache size.

In this example, the .wrap method is called on the routine, but of course you can do whatever you want. Common applications are mixing roles into the routine or adding them to a dispatch table.

Traits can not only be applied to routines, but also to parameters, attributes and variables. For example writable accessors are realized with the is rw trait:

class Book {
has @.pages is rw;
...
}

Traits are also used to attach documentation to classes and attributes (stay tuned for an addvent calendar post on Pod6), marking routine parameters as writable and declaring class inheritance and role application.

This flexibility makes them ideal for writing libraries that make the user code look like a domain-specific language, and supplying meta data in a safe way.

Maybe I haven’t had enough coffee, or maybe the spec is wrong, misleading, or overly ambitious, but my simple read of it this is that:
A) WHICH is intended for hashing and comparing of objects …
B) … that are often not value types, and that …
C) … the capture class could “define a .WHICH method that makes different [captures] look like the same object if they happen to have the same contents.”

I was imagining a capture would walk the tree of objects it contains, collecting WHICHs. If any object doesn’t return a WHICH value, the walk ends and the capture fails to cache. If any object returns an ObjAt which ignores the “same content” issue, then the capture, if cached, ends up taking space in the cache but never matches.

.WHICH is indeed used for hashing and comparison, but not the same kind of comparison that is cached needs. It does object identity comparsion (like the === operator), but caching needs object equivalence comparsion (like the eqv operator). Only for value types are the two comparison semantics the same.

Each call to a subroutine creates a new Capture object, so comparison with .WHICH and hashing will never find a match.

> I don’t think that second part really works, because every capture will be a unique object.

I wondered about that.

http://perlcabal.org/syn/S02.html#The_.WHICH_Method_for_Value_Types says
“Every object can produce a “WHICH” value that uniquely identifies the object for hashing and other value-based comparisons. Normal objects just use their location as their identity, but if a class wishes to behave as a value type, it can define a .WHICH method that makes different objects look like the same object if they happen to have the same contents.”