4
4
[ ![ Build Status] ( https://ci.appveyor.com/api/projects/status/github/mauro3/SimpleTraits.jl?branch=master&svg=true )] ( https://ci.appveyor.com/project/mauro3/simpletraits-jl/branch/master )
5
5
[ NEWS] ( NEWS.md )
6
6
7
- [ ![ SimpleTraits] ( http://pkg.julialang.org/badges/SimpleTraits_0.5.svg )] ( http://pkg.julialang.org/?pkg=SimpleTraits )
8
7
[ ![ SimpleTraits] ( http://pkg.julialang.org/badges/SimpleTraits_0.6.svg )] ( http://pkg.julialang.org/?pkg=SimpleTraits )
8
+ [ ![ SimpleTraits] ( http://pkg.julialang.org/badges/SimpleTraits_0.7.svg )] ( http://pkg.julialang.org/detail/SimpleTraits )
9
9
10
10
This package provides a macro-based implementation of traits, using
11
11
[ Tim Holy's trait trick] ( https://github.com/JuliaLang/julia/issues/2345#issuecomment-54537633 ) .
@@ -78,15 +78,15 @@ Notes:
78
78
79
79
It can be checked whether a type belongs to a trait with ` istrait ` :
80
80
``` julia
81
- using Base . Test
81
+ using Test
82
82
@test istrait (IsNice{Int})
83
83
@test ! istrait (BelongTogether{Int,Int}) # only BelongTogether{Int,String} was added above
84
84
```
85
85
86
86
Functions which dispatch on traits are constructed like:
87
87
``` julia
88
- @traitfn f {X; IsNice{X}} (x :: X ) = " Very nice!"
89
- @traitfn f {X; !IsNice{X}} (x :: X ) = " Not so nice!"
88
+ @traitfn f (x :: X ) where {X; IsNice{X}} = " Very nice!"
89
+ @traitfn f (x :: X ) where {X; ! IsNice{X}} = " Not so nice!"
90
90
```
91
91
This means that a type ` X ` which is part of the trait ` IsNice ` will
92
92
dispatch to the method returning ` "Very nice!" ` , otherwise to the one
@@ -101,11 +101,11 @@ function. Thus there is no extra mental gymnastics required for a
101
101
102
102
Similarly for ` BelongTogether ` which has two parameters:
103
103
``` julia
104
- @traitfn f {X,Y; BelongTogether{X,Y}} (x :: X ,y :: Y ) = " $x and $y forever!"
104
+ @traitfn f (x :: X ,y :: Y ) where {X,Y; BelongTogether{X,Y}} = " $x and $y forever!"
105
105
@test f (5 , " b" )== " 5 and b forever!"
106
106
@test_throws MethodError f (5 , 5 )
107
107
108
- @traitfn f {X,Y; !BelongTogether{X,Y}} (x :: X ,y :: Y ) = " $x and $y cannot stand each other!"
108
+ @traitfn f (x :: X ,y :: Y ) where {X,Y; ! BelongTogether{X,Y}} = " $x and $y cannot stand each other!"
109
109
@test f (5 , 5 )== " 5 and 5 cannot stand each other!"
110
110
```
111
111
@@ -172,8 +172,8 @@ Example:
172
172
@traitdef Tr{X}
173
173
174
174
fn (x:: Integer ) = 1 # a normal method
175
- @traitfn fn {X<:AbstractFloat; Tr{X}} (x :: X ) = 2
176
- @traitfn fn {X<:AbstractFloat; !Tr{X}} (x :: X ) = 3
175
+ @traitfn fn (x :: X ) where {X<: AbstractFloat ; Tr{X}} = 2
176
+ @traitfn fn (x :: X ) where {X<: AbstractFloat ; ! Tr{X}} = 3
177
177
178
178
@traitimpl Tr{Float32}
179
179
@traitimpl Tr{Int} # this does not impact dispatch of `fn`
@@ -188,15 +188,15 @@ one trait. Continuing above example, this *does not work* as one may
188
188
expect:
189
189
``` julia
190
190
@traitdef Tr2{X}
191
- @traitfn fn {X<:AbstractFloat; Tr2{X}} (x :: X ) = 4
191
+ @traitfn fn (x :: X ) where {X<: AbstractFloat ; Tr2{X}} = 4
192
192
193
193
@traitimpl Tr2{Float16}
194
194
fn (Float16 (5 )) # -> 4; dispatch through traits
195
195
fn (Float32 (5 )) # -> MethodError; method defined in previous example
196
196
# was overwritten above
197
197
```
198
198
This last definition of ` fn ` just overwrites the definition `@traitfn
199
- f{X; Tr{X}}(x::X) = 2` from above.
199
+ f(x::X) where {X; Tr{X}} = 2` from above.
200
200
201
201
If you need to dispatch on several traits in a single trait-method,
202
202
then you're out of luck. But please voice your grievance over in pull
@@ -327,7 +327,7 @@ Julia 0.5 one could use a generated function but not anymore in Julia 0.6.)
327
327
328
328
Note also that trait functions can be generated functions:
329
329
``` julia
330
- @traitfn @generated fg {X; IsNice{X}} (x :: X ) = (println (x); :x )
330
+ @traitfn @generated fg (x :: X ) where {X; IsNice{X}} = (println (x); :x )
331
331
```
332
332
333
333
# Innards
@@ -346,16 +346,16 @@ julia> macroexpand(:(@traitimpl Tr{Int}))
346
346
SimpleTraits. trait {X1 <: Int} (:: Type{Tr{X1}} ) = Tr{X1}
347
347
SimpleTraits. istrait {X1 <: Int} (:: Type{Tr{X1}} ) = true # for convenience, really
348
348
349
- julia> macroexpand (:(@traitfn g {X; Tr{X}} (x :: X ) = x+ 1 ))
349
+ julia> macroexpand (:(@traitfn g (x :: X ) where {X; Tr{X}}= x+ 1 ))
350
350
351
- @inline g {X} (x:: X ) = g (trait (Tr{X}), x) # this is Tim's trick, using above grouping-function
352
- g {X} (:: Type{Tr{X}} ,x:: X ) = x + 1 # this is the logic
351
+ @inline g (x:: X ) where {X} = g (trait (Tr{X}), x) # this is Tim's trick, using above grouping-function
352
+ g (:: Type{Tr{X}} ,x:: X ) where {X} = x + 1 # this is the logic
353
353
354
- julia> macroexpand (:(@traitfn g {X; !Tr{X}} (x :: X ) = x+ 1000 ))
354
+ julia> macroexpand (:(@traitfn g (x :: X ) where {X; ! Tr{X}}= x+ 1000 ))
355
355
356
356
# the trait dispatch helper function needn't be defined twice,
357
357
# only the logic:
358
- g {X} (:: Type{ Not{Tr{X}} } , x:: X ) = x + 1000
358
+ g (:: Type{ Not{Tr{X}} } , x:: X ) where {X} = x + 1000
359
359
```
360
360
361
361
For a detailed explanation of how Tim's trick works, see
@@ -372,8 +372,8 @@ definitions.
372
372
Example, dispatch on whether an argument is immutable or not:
373
373
374
374
``` julia
375
- @traitfn f {X; IsImmutable{X}} (x :: X ) = X (x. fld+ 1 ) # make a new instance
376
- @traitfn f {X; !IsImmutable{X}} (x :: X ) = (x. fld += 1 ; x) # update in-place
375
+ @traitfn f (x :: X ) where {X; IsImmutable{X}} = X (x. fld+ 1 ) # make a new instance
376
+ @traitfn f (x :: X ) where {X; ! IsImmutable{X}} = (x. fld += 1 ; x) # update in-place
377
377
378
378
# use
379
379
mutable struct A; fld end
0 commit comments