Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/coldencullen/quack
A compile-time duck typing library for D.
https://github.com/coldencullen/quack
Last synced: about 18 hours ago
JSON representation
A compile-time duck typing library for D.
- Host: GitHub
- URL: https://github.com/coldencullen/quack
- Owner: ColdenCullen
- License: mit
- Created: 2014-08-01T04:07:58.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2020-11-02T02:08:43.000Z (about 4 years ago)
- Last Synced: 2024-04-14T18:29:45.636Z (9 months ago)
- Language: D
- Size: 32.2 KB
- Stars: 6
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## quack
[![Build Status](http://img.shields.io/travis/ColdenCullen/quack/master.svg?style=flat)](https://travis-ci.org/ColdenCullen/quack)
[![Coverage](http://img.shields.io/coveralls/ColdenCullen/quack/master.svg?style=flat)](https://coveralls.io/r/ColdenCullen/quack)
[![Release](http://img.shields.io/github/release/ColdenCullen/quack.svg?style=flat)](http://code.dlang.org/packages/quack)A library for enabling compile-time duck typing in D.
#### Duck Typing
Duck typing is a reference to the phrase "if it walks like a duck, and quacks
like a duck, then it's probably a duck." The idea is that if a `struct` or
`class` has all the same members as another, it should be usable as the other.#### Usage
Duck exists so that you may treat non-related types as polymorphic, at compile
time. There are three primary ways to use quack:1) Taking objects as arguments: For this, you should use `extends!( A, B )`,
which returns true if A "extends" B. It can do this by implementing all of the
same members B has, or by having a variable of type B that it has set to
`alias this`.2) Storing pointers to objects: For this, you should use a `DuckPointer!A`,
which can be created with `duck!A( B b )`, assuming B "extends" A (the actual
check is done using `extends`, so see the docs on that). Note that this approach
should only be used when you need to actually store the object, as it is much
slower than the pure template approach.3) Checking for the presence of a mixin: For this, you'll want
`hasStringMixin!( A, mix )` or `hasTemplateMixin!( A, mix )`. These two
templates will instantiate a struct with the given mixin, `mix`, and check if it is
compatible with the type given, `A`.#### Examples
```d
import quack;
import std.stdio;struct Base
{
int x;
}struct Child1
{
Base b;
alias b this;
}struct Child2
{
int x;
}void someFunction( T )( T t ) if( extends!( T, Base ) )
{
writeln( t.x );
}struct HolderOfBase
{
DuckPointer!Base myBase;
}void main()
{
someFunction( Child1() );
someFunction( Child2() );auto aHolder1 = new HolderOfA( duck!Base( Child1() ) );
auto aHolder2 = new HolderOfA( duck!Base( Child2() ) );
}
``````d
import quack;
import std.stdio;enum myStringMixin = q{
void stringMember();
};mixin template MyTemplateMixin( MemberType )
{
MemberType templateMember;
}void doAThing( T )( T t ) if( hasTemplateMixin!( T, MyTemplateMixin, float ) )
{
// Doing a thing...
}void doAnotherThing( T )( T t ) if( hasStringMixin!( T, myStringMixin ) )
{
// Still doing things...
}struct TemplateMixinImpl
{
mixin MyTemplateMixin!float;
}struct StringMixinImpl
{
mixin( myStringMixin );
}void main()
{
doAThing( TemplateMixinImpl() );
doAnotherThing( StringMixinImpl() );
}
```