Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
5
Task/Constrained-genericity/00-META.yaml
Normal file
5
Task/Constrained-genericity/00-META.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Type System
|
||||
from: http://rosettacode.org/wiki/Constrained_genericity
|
||||
note: Object oriented
|
||||
15
Task/Constrained-genericity/00-TASK.txt
Normal file
15
Task/Constrained-genericity/00-TASK.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
'''Constrained genericity''' or '''bounded quantification''' means
|
||||
that a parametrized type or function (see [[parametric polymorphism]])
|
||||
can only be instantiated on types fulfilling some conditions,
|
||||
even if those conditions are not used in that function.
|
||||
|
||||
Say a type is called "eatable" if you can call the function <tt>eat</tt> on it.
|
||||
Write a generic type <tt>FoodBox</tt> which contains a collection of objects of
|
||||
a type given as parameter, but can only be instantiated on eatable types.
|
||||
The FoodBox shall not use the function eat in any way (i.e. without the explicit restriction, it could be instantiated on any type).
|
||||
The specification of a type being eatable should be as generic as possible
|
||||
in your language (i.e. the restrictions on the implementation of eatable types
|
||||
should be as minimal as possible).
|
||||
Also explain the restrictions, if any, on the implementation of eatable types,
|
||||
and show at least one example of an eatable type.
|
||||
|
||||
24
Task/Constrained-genericity/Ada/constrained-genericity-1.ada
Normal file
24
Task/Constrained-genericity/Ada/constrained-genericity-1.ada
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
with Ada.Containers.Indefinite_Vectors;
|
||||
|
||||
package Nutrition is
|
||||
type Food is interface;
|
||||
procedure Eat (Object : in out Food) is abstract;
|
||||
|
||||
end Nutrition;
|
||||
|
||||
with Ada.Containers;
|
||||
with Nutrition;
|
||||
|
||||
generic
|
||||
type New_Food is new Nutrition.Food;
|
||||
package Food_Boxes is
|
||||
|
||||
package Food_Vectors is
|
||||
new Ada.Containers.Indefinite_Vectors
|
||||
( Index_Type => Positive,
|
||||
Element_Type => New_Food
|
||||
);
|
||||
|
||||
subtype Food_Box is Food_Vectors.Vector;
|
||||
|
||||
end Food_Boxes;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
type Banana is new Food with null record;
|
||||
overriding procedure Eat (Object : in out Banana) is null;
|
||||
package Banana_Box is new Food_Boxes (Banana);
|
||||
|
||||
type Tomato is new Food with null record;
|
||||
overriding procedure Eat (Object : in out Tomato) is null;
|
||||
package Tomato_Box is new Food_Boxes (Tomato);
|
||||
-- We have declared Banana and Tomato as a Food.
|
||||
33
Task/Constrained-genericity/C++/constrained-genericity.cpp
Normal file
33
Task/Constrained-genericity/C++/constrained-genericity.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
template<typename T> //Detection helper struct
|
||||
struct can_eat //Detects presence of non-const member function void eat()
|
||||
{
|
||||
private:
|
||||
template<typename U, void (U::*)()> struct SFINAE {};
|
||||
template<typename U> static char Test(SFINAE<U, &U::eat>*);
|
||||
template<typename U> static int Test(...);
|
||||
public:
|
||||
static constexpr bool value = sizeof(Test<T>(0)) == sizeof(char);
|
||||
};
|
||||
|
||||
struct potato
|
||||
{ void eat(); };
|
||||
|
||||
struct brick
|
||||
{};
|
||||
|
||||
template<typename T>
|
||||
class FoodBox
|
||||
{
|
||||
//Using static assertion to prohibit non-edible types
|
||||
static_assert(can_eat<T>::value, "Only edible items are allowed in foodbox");
|
||||
|
||||
//Rest of class definition
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
FoodBox<potato> lunch;
|
||||
|
||||
//Following leads to compile-time error
|
||||
//FoodBox<brick> practical_joke;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
interface IEatable
|
||||
{
|
||||
void Eat();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
class FoodBox<T> where T : IEatable
|
||||
{
|
||||
List<T> food;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class Apple : IEatable
|
||||
{
|
||||
public void Eat()
|
||||
{
|
||||
System.Console.WriteLine("Apple has been eaten");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic
|
||||
|
||||
class FoodMakingBox<T> where T : IEatable, new()
|
||||
{
|
||||
List<T> food;
|
||||
|
||||
void Make(int numberOfFood)
|
||||
{
|
||||
this.food = new List<T>();
|
||||
for (int i = 0; i < numberOfFood; i++)
|
||||
{
|
||||
this.food.Add(new T());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
(defclass food () ())
|
||||
|
||||
(defclass inedible-food (food) ())
|
||||
|
||||
(defclass edible-food (food) ())
|
||||
|
||||
(defgeneric eat (foodstuff)
|
||||
(:documentation "Eat the foodstuff."))
|
||||
|
||||
(defmethod eat ((foodstuff edible-food))
|
||||
"A specialized method for eating edible-food."
|
||||
(format nil "Eating ~w." foodstuff))
|
||||
|
||||
(defun eatable-p (thing)
|
||||
"Returns true if there are eat methods defined for thing."
|
||||
(not (endp (compute-applicable-methods #'eat (list thing)))))
|
||||
|
||||
(deftype eatable ()
|
||||
"Eatable objects are those satisfying eatable-p."
|
||||
'(satisfies eatable-p))
|
||||
|
||||
(defun make-food-box (extra-type &rest array-args)
|
||||
"Returns an array whose element-type is (and extra-type food).
|
||||
array-args should be suitable for MAKE-ARRAY, and any provided
|
||||
element-type keyword argument is ignored."
|
||||
(destructuring-bind (dimensions &rest array-args) array-args
|
||||
(apply 'make-array dimensions
|
||||
:element-type `(and ,extra-type food)
|
||||
array-args)))
|
||||
|
||||
(defun make-eatable-food-box (&rest array-args)
|
||||
"Return an array whose elements are declared to be of type (and
|
||||
eatable food)."
|
||||
(apply 'make-food-box 'eatable array-args))
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
class Apple
|
||||
def eat
|
||||
end
|
||||
end
|
||||
|
||||
class Carrot
|
||||
def eat
|
||||
end
|
||||
end
|
||||
|
||||
class FoodBox(T)
|
||||
def initialize(@data : Array(T))
|
||||
{% if T.union? %}
|
||||
{% raise "All items should be eatable" unless T.union_types.all? &.has_method?(:eat) %}
|
||||
{% else %}
|
||||
{% raise "Items should be eatable" unless T.has_method?(:eat) %}
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
|
||||
FoodBox.new([Apple.new, Apple.new])
|
||||
FoodBox.new([Apple.new, Carrot.new])
|
||||
FoodBox.new([Apple.new, Carrot.new, 123])
|
||||
19
Task/Constrained-genericity/D/constrained-genericity-1.d
Normal file
19
Task/Constrained-genericity/D/constrained-genericity-1.d
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
enum IsEdible(T) = is(typeof(T.eat));
|
||||
|
||||
struct FoodBox(T) if (IsEdible!T) {
|
||||
T[] food;
|
||||
alias food this;
|
||||
}
|
||||
|
||||
struct Carrot {
|
||||
void eat() {}
|
||||
}
|
||||
|
||||
static struct Car {}
|
||||
|
||||
void main() {
|
||||
FoodBox!Carrot carrotsBox; // OK
|
||||
carrotsBox ~= Carrot(); // Adds a carrot
|
||||
|
||||
//FoodBox!Car carsBox; // Not allowed
|
||||
}
|
||||
17
Task/Constrained-genericity/D/constrained-genericity-2.d
Normal file
17
Task/Constrained-genericity/D/constrained-genericity-2.d
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
interface IEdible { void eat(); }
|
||||
|
||||
struct FoodBox(T : IEdible) {
|
||||
T[] food;
|
||||
alias food this;
|
||||
}
|
||||
|
||||
class Carrot : IEdible {
|
||||
void eat() {}
|
||||
}
|
||||
|
||||
class Car {}
|
||||
|
||||
void main() {
|
||||
FoodBox!Carrot carrotBox; // OK
|
||||
//FoodBox!Car carBox; // Not allowed
|
||||
}
|
||||
14
Task/Constrained-genericity/E/constrained-genericity.e
Normal file
14
Task/Constrained-genericity/E/constrained-genericity.e
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/** Guard accepting only objects with an 'eat' method */
|
||||
def Eatable {
|
||||
to coerce(specimen, ejector) {
|
||||
if (Ref.isNear(specimen) && specimen.__respondsTo("eat", 0)) {
|
||||
return specimen
|
||||
} else {
|
||||
throw.eject(ejector, `inedible: $specimen`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def makeFoodBox() {
|
||||
return [].diverge(Eatable) # A guard-constrained list
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
deferred class
|
||||
EATABLE
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
eat
|
||||
-- Eat this eatable substance
|
||||
deferred
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
class
|
||||
APPLE
|
||||
|
||||
inherit
|
||||
EATABLE
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
eat
|
||||
-- Consume
|
||||
do
|
||||
print ("One apple eaten%N")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
class
|
||||
PEAR
|
||||
|
||||
inherit
|
||||
EATABLE
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
eat
|
||||
-- Consume
|
||||
do
|
||||
print ("One pear eaten%N")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
class
|
||||
FOOD_BOX [G -> EATABLE]
|
||||
|
||||
inherit
|
||||
ARRAYED_LIST [G]
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
my_apple_box: FOOD_BOX [APPLE]
|
||||
|
|
@ -0,0 +1 @@
|
|||
my_refrigerator: FOOD_BOX [EATABLE]
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
class
|
||||
APPLICATION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
do
|
||||
create my_apple_box.make (10)
|
||||
create one_apple
|
||||
create one_pear
|
||||
my_apple_box.extend (one_apple)
|
||||
-- my_apple_box.extend (one_pear)
|
||||
across
|
||||
my_apple_box as ic
|
||||
loop
|
||||
ic.item.eat
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
my_apple_box: FOOD_BOX [APPLE]
|
||||
-- My apple box
|
||||
|
||||
one_apple: APPLE
|
||||
-- An apple
|
||||
|
||||
one_pear: PEAR
|
||||
-- A pear
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
-- my_apple_box.extend (one_pear)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
type ^a FoodBox // a generic type FoodBox
|
||||
when ^a: (member eat: unit -> string) // with an explicit member constraint on ^a,
|
||||
(items:^a list) = // a one-argument constructor
|
||||
member inline x.foodItems = items // and a public read-only property
|
||||
|
||||
// a class type that fullfills the member constraint
|
||||
type Banana() =
|
||||
member x.eat() = "I'm eating a banana."
|
||||
|
||||
// an instance of a Banana FoodBox
|
||||
let someBananas = FoodBox [Banana(); Banana()]
|
||||
39
Task/Constrained-genericity/Forth/constrained-genericity.fth
Normal file
39
Task/Constrained-genericity/Forth/constrained-genericity.fth
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
include FMS-SI.f
|
||||
include FMS-SILib.f
|
||||
:class Eatable
|
||||
:m eat ." successful eat " ;m
|
||||
;class
|
||||
|
||||
\ FoodBox is defined without inspecting for the eat message
|
||||
:class FoodBox
|
||||
object-list eatable-types
|
||||
:m init: eatable-types init: ;m
|
||||
:m add: ( obj -- )
|
||||
dup is-kindOf Eatable
|
||||
if eatable-types add:
|
||||
else drop ." not an eatable type "
|
||||
then ;m
|
||||
:m test
|
||||
begin eatable-types each:
|
||||
while eat
|
||||
repeat ;m
|
||||
;class
|
||||
|
||||
FoodBox aFoodBox
|
||||
Eatable aEatable
|
||||
aEatable aFoodBox add: \ add the e1 object to the object-list
|
||||
aFoodBox test \ => successful eat
|
||||
|
||||
:class brick
|
||||
:m eat cr ." successful eat " ;m
|
||||
;class
|
||||
|
||||
brick abrick \ create an object that is not eatable
|
||||
abrick aFoodBox add: \ => not an eatable type
|
||||
|
||||
:class apple <super Eatable
|
||||
;class
|
||||
|
||||
apple anapple
|
||||
anapple aFoodBox add:
|
||||
aFoodBox test \ => successful eat successful eat
|
||||
42
Task/Constrained-genericity/Fortran/constrained-genericity.f
Normal file
42
Task/Constrained-genericity/Fortran/constrained-genericity.f
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
module cg
|
||||
implicit none
|
||||
|
||||
type, abstract :: eatable
|
||||
end type eatable
|
||||
|
||||
type, extends(eatable) :: carrot_t
|
||||
end type carrot_t
|
||||
|
||||
type :: brick_t; end type brick_t
|
||||
|
||||
type :: foodbox
|
||||
class(eatable), allocatable :: food
|
||||
contains
|
||||
procedure, public :: add_item => add_item_fb
|
||||
end type foodbox
|
||||
|
||||
contains
|
||||
|
||||
subroutine add_item_fb(this, f)
|
||||
class(foodbox), intent(inout) :: this
|
||||
class(eatable), intent(in) :: f
|
||||
allocate(this%food, source=f)
|
||||
end subroutine add_item_fb
|
||||
end module cg
|
||||
|
||||
|
||||
program con_gen
|
||||
use cg
|
||||
implicit none
|
||||
|
||||
type(carrot_t) :: carrot
|
||||
type(brick_t) :: brick
|
||||
type(foodbox) :: fbox
|
||||
|
||||
! Put a carrot into the foodbox
|
||||
call fbox%add_item(carrot)
|
||||
|
||||
! Try to put a brick in - results in a compiler error
|
||||
call fbox%add_item(brick)
|
||||
|
||||
end program con_gen
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
type eatable interface {
|
||||
eat()
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
type foodbox []eatable
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
type peelfirst string
|
||||
|
||||
func (f peelfirst) eat() {
|
||||
// peel code goes here
|
||||
fmt.Println("mm, that", f, "was good!")
|
||||
}
|
||||
22
Task/Constrained-genericity/Go/constrained-genericity-4.go
Normal file
22
Task/Constrained-genericity/Go/constrained-genericity-4.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
type eatable interface {
|
||||
eat()
|
||||
}
|
||||
|
||||
type foodbox []eatable
|
||||
|
||||
type peelfirst string
|
||||
|
||||
func (f peelfirst) eat() {
|
||||
// peel code goes here
|
||||
fmt.Println("mm, that", f, "was good!")
|
||||
}
|
||||
|
||||
func main() {
|
||||
fb := foodbox{peelfirst("banana"), peelfirst("mango")}
|
||||
f0 := fb[0]
|
||||
f0.eat()
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
class Eatable a where
|
||||
eat :: a -> String
|
||||
|
|
@ -0,0 +1 @@
|
|||
data (Eatable a) => FoodBox a = F [a]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
data Banana = Foo -- the implementation doesn't really matter in this case
|
||||
instance Eatable Banana where
|
||||
eat _ = "I'm eating a banana"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
instance Eatable Double where
|
||||
eat d = "I'm eating " ++ show d
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
class Food a where
|
||||
munch :: a -> String
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
instance (Food a) => Eatable a where
|
||||
eat x = munch x
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import Utils # From the UniLib package to get the Class class.
|
||||
|
||||
class Eatable:Class()
|
||||
end
|
||||
|
||||
class Fish:Eatable(name)
|
||||
method eat(); write("Eating "+name); end
|
||||
end
|
||||
|
||||
class Rock:Class(name)
|
||||
method eat(); write("Eating "+name); end
|
||||
end
|
||||
|
||||
class FoodBox(A)
|
||||
initially
|
||||
every item := !A do if "Eatable" == item.Type() then next else bad := "yes"
|
||||
return /bad
|
||||
end
|
||||
|
||||
procedure main()
|
||||
if FoodBox([Fish("salmon")]) then write("Edible") else write("Inedible")
|
||||
if FoodBox([Rock("granite")]) then write("Edible") else write("Inedible")
|
||||
end
|
||||
14
Task/Constrained-genericity/J/constrained-genericity-1.j
Normal file
14
Task/Constrained-genericity/J/constrained-genericity-1.j
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
coclass'Connoisseur'
|
||||
isEdible=:3 :0
|
||||
0<nc<'eat__y'
|
||||
)
|
||||
|
||||
coclass'FoodBox'
|
||||
create=:3 :0
|
||||
collection=: 0#y
|
||||
)
|
||||
add=:3 :0"0
|
||||
'inedible' assert isEdible_Connoisseur_ y
|
||||
collection=: collection, y
|
||||
EMPTY
|
||||
)
|
||||
4
Task/Constrained-genericity/J/constrained-genericity-2.j
Normal file
4
Task/Constrained-genericity/J/constrained-genericity-2.j
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
coclass'Apple'
|
||||
eat=:3 :0
|
||||
smoutput'delicious'
|
||||
)
|
||||
8
Task/Constrained-genericity/J/constrained-genericity-3.j
Normal file
8
Task/Constrained-genericity/J/constrained-genericity-3.j
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
lunch=:'' conew 'FoodBox'
|
||||
a1=: conew 'Apple'
|
||||
a2=: conew 'Apple'
|
||||
add__lunch a1
|
||||
add__lunch a2
|
||||
george=: conew 'Connoisseur'
|
||||
add__lunch george
|
||||
|inedible: assert
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
interface Eatable
|
||||
{
|
||||
void eat();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import java.util.List;
|
||||
|
||||
class FoodBox<T extends Eatable>
|
||||
{
|
||||
public List<T> food;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
public <T extends Eatable> void foo(T x) { }
|
||||
// although in this case this is no more useful than just "public void foo(Eatable x)"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
public class Test{
|
||||
public <T extends Eatable> void bar(){ }
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
test.<EatableClass>bar();
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
abstract type Edible end
|
||||
eat(::Edible) = "Yum!"
|
||||
|
||||
mutable struct FoodBox{T<:Edible}
|
||||
food::Vector{T}
|
||||
end
|
||||
|
||||
struct Carrot <: Edible
|
||||
variety::AbstractString
|
||||
end
|
||||
|
||||
struct Brick
|
||||
volume::Float64
|
||||
end
|
||||
|
||||
c = Carrot("Baby")
|
||||
b = Brick(125.0)
|
||||
eat(c)
|
||||
eat(b)
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// version 1.0.6
|
||||
|
||||
interface Eatable {
|
||||
fun eat()
|
||||
}
|
||||
|
||||
class Cheese(val name: String) : Eatable {
|
||||
override fun eat() {
|
||||
println("Eating $name")
|
||||
}
|
||||
|
||||
override fun toString() = name
|
||||
}
|
||||
|
||||
class Meat(val name: String) : Eatable {
|
||||
override fun eat() {
|
||||
println("Eating $name")
|
||||
}
|
||||
|
||||
override fun toString() = name
|
||||
}
|
||||
|
||||
class FoodBox<T: Eatable> {
|
||||
private val foodList = mutableListOf<T>()
|
||||
|
||||
fun add(food: T) {
|
||||
foodList.add(food)
|
||||
}
|
||||
|
||||
override fun toString() = foodList.toString()
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val cheddar = Cheese("cheddar")
|
||||
val feta = Cheese("feta")
|
||||
val cheeseBox = FoodBox<Cheese>()
|
||||
cheeseBox.add(cheddar)
|
||||
cheeseBox.add(feta)
|
||||
println("CheeseBox contains : $cheeseBox")
|
||||
|
||||
val beef = Meat("beef")
|
||||
val ham = Meat("ham")
|
||||
val meatBox = FoodBox<Meat>()
|
||||
meatBox.add(beef)
|
||||
meatBox.add(ham)
|
||||
println("MeatBox contains : $meatBox")
|
||||
|
||||
cheddar.eat()
|
||||
beef.eat()
|
||||
println("Full now!")
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
import morfa.type.traits;
|
||||
|
||||
template < T >
|
||||
alias IsEdible = HasMember< T, "eat" >;
|
||||
|
||||
template < T >
|
||||
if (IsEdible< T >)
|
||||
struct FoodBox
|
||||
{
|
||||
var food: T[];
|
||||
}
|
||||
|
||||
struct Carrot
|
||||
{
|
||||
func eat(): void {}
|
||||
}
|
||||
|
||||
struct Car {}
|
||||
|
||||
func main(): void
|
||||
{
|
||||
var carrotBox: FoodBox< Carrot >; // OK
|
||||
carrotBox.food ~= Carrot(); // Adds a carrot
|
||||
|
||||
// var carBox: FoodBox< Car >; // Not allowed
|
||||
static assert( not trait(compiles, func() { var carBox: FoodBox< Car >; } ));
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
interface IEdible
|
||||
{
|
||||
public func eat(): void;
|
||||
}
|
||||
|
||||
template < T >
|
||||
if (IsDerivedOf< T, IEdible >)
|
||||
struct FoodBox
|
||||
{
|
||||
var food: T[];
|
||||
}
|
||||
|
||||
class Carrot: IEdible
|
||||
{
|
||||
public override func eat(): void {}
|
||||
}
|
||||
|
||||
class Car {}
|
||||
|
||||
func main(): void
|
||||
{
|
||||
var carrotBox: FoodBox< Carrot >; // OK
|
||||
|
||||
// var carBox: FoodBox< Car >; // Not allowed
|
||||
static assert( not trait(compiles, func() { var carBox: FoodBox< Car >; } ));
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
interface IEatable
|
||||
{
|
||||
Eat() : void;
|
||||
}
|
||||
|
||||
class FoodBox[T] : IEnumerable[T]
|
||||
where T : IEatable
|
||||
{
|
||||
private _foods : list[T] = [];
|
||||
|
||||
public this() {}
|
||||
|
||||
public this(items : IEnumerable[T])
|
||||
{
|
||||
this._foods = $[food | food in items];
|
||||
}
|
||||
|
||||
public Add(food : T) : FoodBox[T]
|
||||
{
|
||||
FoodBox(food::_foods);
|
||||
}
|
||||
|
||||
public GetEnumerator() : IEnumerator[T]
|
||||
{
|
||||
_foods.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
class Apple : IEatable
|
||||
{
|
||||
public this() {}
|
||||
|
||||
public Eat() : void
|
||||
{
|
||||
System.Console.WriteLine("nom..nom..nom");
|
||||
}
|
||||
}
|
||||
|
||||
mutable appleBox = FoodBox();
|
||||
repeat(3) {
|
||||
appleBox = appleBox.Add(Apple());
|
||||
}
|
||||
|
||||
foreach (apple in appleBox) apple.Eat();
|
||||
21
Task/Constrained-genericity/Nim/constrained-genericity.nim
Normal file
21
Task/Constrained-genericity/Nim/constrained-genericity.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
type
|
||||
Eatable = concept e
|
||||
eat(e)
|
||||
|
||||
FoodBox[e: Eatable] = seq[e]
|
||||
|
||||
Food = object
|
||||
name: string
|
||||
count: int
|
||||
|
||||
proc eat(x: int) = echo "Eating the int: ", x
|
||||
proc eat(x: Food) = echo "Eating ", x.count, " ", x.name, "s"
|
||||
|
||||
var ints = FoodBox[int](@[1,2,3,4,5])
|
||||
var fs = FoodBox[Food](@[])
|
||||
|
||||
fs.add Food(name: "Hamburger", count: 3)
|
||||
fs.add Food(name: "Cheeseburger", count: 5)
|
||||
|
||||
for f in fs:
|
||||
eat(f)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module type Eatable = sig
|
||||
type t
|
||||
val eat : t -> unit
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module MakeFoodBox(A : Eatable) = struct
|
||||
type elt = A.t
|
||||
type t = F of elt list
|
||||
let make_box_from_list xs = F xs
|
||||
end
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
type banana = Foo (* a dummy type *)
|
||||
|
||||
module Banana : Eatable with type t = banana = struct
|
||||
type t = banana
|
||||
let eat _ = print_endline "I'm eating a banana"
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
module EatFloat : Eatable with type t = float = struct
|
||||
type t = float
|
||||
let eat f = Printf.printf "I'm eating %f\n%!" f
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module BananaBox = MakeFoodBox (Banana)
|
||||
module FloatBox = MakeFoodBox (EatFloat)
|
||||
|
||||
let my_box = BananaBox.make_box_from_list [Foo]
|
||||
let your_box = FloatBox.make_box_from_list [2.3; 4.5]
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
use Collection.Generic;
|
||||
|
||||
interface Eatable {
|
||||
method : virtual : Eat() ~ Nil;
|
||||
}
|
||||
|
||||
class FoodBox<T : Eatable> {
|
||||
food : List<T>;
|
||||
}
|
||||
|
||||
class Plum implements Eatable {
|
||||
method : Eat() ~ Nil {
|
||||
"Yummy Plum!"->PrintLine();
|
||||
}
|
||||
}
|
||||
|
||||
class Genericity {
|
||||
function : Main(args : String[]) ~ Nil {
|
||||
plums : FoodBox<Plum>;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
@protocol Eatable
|
||||
- (void)eat;
|
||||
@end
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
@interface FoodBox<T : id<Eatable>> : NSObject
|
||||
@end
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
call dinnerTime "yogurt"
|
||||
call dinnerTime .pizza~new
|
||||
call dinnerTime .broccoli~new
|
||||
|
||||
|
||||
-- a mixin class that defines the interface for being "food", and
|
||||
-- thus expected to implement an "eat" method
|
||||
::class food mixinclass object
|
||||
::method eat abstract
|
||||
|
||||
::class pizza subclass food
|
||||
::method eat
|
||||
Say "mmmmmmmm, pizza".
|
||||
|
||||
-- mixin classes can also be used for multiple inheritance
|
||||
::class broccoli inherit food
|
||||
::method eat
|
||||
Say "ugh, do I have to?".
|
||||
|
||||
::routine dinnerTime
|
||||
use arg dish
|
||||
-- ooRexx arguments are typeless, so tests for constrained
|
||||
-- types must be peformed at run time. The isA method will
|
||||
-- check if an object is of the required type
|
||||
if \dish~isA(.food) then do
|
||||
say "I can't eat that!"
|
||||
return
|
||||
end
|
||||
else dish~eat
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
macro Gluttony(vartype, capacity, foodlist)
|
||||
'==========================================
|
||||
|
||||
typedef vartype physical
|
||||
|
||||
enum food foodlist
|
||||
|
||||
type ActualFood
|
||||
sys name
|
||||
physical size
|
||||
physical quantity
|
||||
end type
|
||||
|
||||
Class foodbox
|
||||
'============
|
||||
has ActualFood Item[capacity]
|
||||
sys max
|
||||
|
||||
method put(sys f, physical s,q)
|
||||
max++
|
||||
Item[max]<=f,s,q
|
||||
end method
|
||||
|
||||
method GetNext(ActualFood *Stuff)
|
||||
if max then
|
||||
copy @stuff,@Item[max], sizeof Item
|
||||
max--
|
||||
end if
|
||||
end method
|
||||
|
||||
end class
|
||||
|
||||
Class Gourmand
|
||||
'=============
|
||||
physical WeightGain, SleepTime
|
||||
|
||||
method eats(ActualFood *stuff)
|
||||
WeightGain+=stuff.size*stuff.quantity*0.75
|
||||
stuff.size=0
|
||||
stuff.quantity=0
|
||||
end method
|
||||
|
||||
end class
|
||||
|
||||
end macro
|
||||
|
||||
|
||||
'IMPLEMENTATION
|
||||
'==============
|
||||
|
||||
|
||||
Gluttony (
|
||||
double,100,{
|
||||
oyster,trout,bloater,
|
||||
chocolate,truffles,
|
||||
cheesecake,cream,pudding,pie
|
||||
})
|
||||
|
||||
% small 1
|
||||
% medium 2
|
||||
% large 3
|
||||
% huge 7
|
||||
|
||||
% none 0
|
||||
% single 1
|
||||
% few 3
|
||||
% several 7
|
||||
% many 12
|
||||
|
||||
'INSTANCE
|
||||
'========
|
||||
|
||||
FoodBox Hamper
|
||||
Gourmand MrG
|
||||
|
||||
'TEST
|
||||
'====
|
||||
|
||||
Hamper.put food.pudding,large,several
|
||||
Hamper.put food.pie,huge,few
|
||||
ActualFood Course
|
||||
Hamper.GetNext Course
|
||||
MrG.eats Course
|
||||
|
||||
print MrG.WeightGain 'result 15.75
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
include builtins\structs.e as structs
|
||||
|
||||
class foodbox
|
||||
sequence contents = {}
|
||||
procedure add(class food)
|
||||
-- (aside: class food is 100% abstract here...
|
||||
-- ie: class is *the* root|anything class,
|
||||
-- and food is just an arbitrary name)
|
||||
integer t = structs:get_field_flags(food,"eat")
|
||||
if t!=SF_PROC+SF_PUBLIC then
|
||||
throw("not edible") -- no public method eat...
|
||||
end if
|
||||
-- you might also want something like this:
|
||||
-- t = structs:fetch_field(food,"eat")
|
||||
-- if t=NULL then
|
||||
-- throw("eat not implemented")
|
||||
-- end if
|
||||
this.contents = append(this.contents,food)
|
||||
end procedure
|
||||
procedure dine()
|
||||
integer l = length(this.contents)
|
||||
string s = iff(l=1?"":"s")
|
||||
printf(1,"foodbox contains %d item%s\n",{l,s})
|
||||
for i=1 to l do
|
||||
class food = this.contents[i];
|
||||
--food.eat(); -- error...
|
||||
-- If you don't define an [abstract] eat() method, or use
|
||||
-- "class", you end up having to do something like this:
|
||||
integer eat = structs:fetch_field(food,"eat")
|
||||
eat(food)
|
||||
end for
|
||||
end procedure
|
||||
end class
|
||||
foodbox lunchbox = new()
|
||||
|
||||
class fruit
|
||||
string name
|
||||
procedure eat()
|
||||
printf(1,"mmm... %s\n",{this.name})
|
||||
end procedure
|
||||
end class
|
||||
fruit banana = new({"banana"})
|
||||
|
||||
class clay
|
||||
string name = "fletton"
|
||||
end class
|
||||
clay brick = new()
|
||||
|
||||
lunchbox.add(banana)
|
||||
try
|
||||
lunchbox.add(brick) -- throws exception
|
||||
catch e
|
||||
printf(1,"%s line %d error: %s\n",{e[E_FILE],e[E_LINE],e[E_USER]})
|
||||
end try
|
||||
lunchbox.dine()
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
abstract class edible
|
||||
string name
|
||||
procedure eat(); -- (virtual)
|
||||
end class
|
||||
|
||||
class foodbox2
|
||||
sequence contents = {}
|
||||
procedure add(edible food)
|
||||
if food.eat=NULL then -- (optional)
|
||||
throw("eat() not implemented")
|
||||
end if
|
||||
this.contents = append(this.contents,food)
|
||||
end procedure
|
||||
procedure dine()
|
||||
integer l = length(this.contents)
|
||||
string s = iff(l=1?"":"s")
|
||||
printf(1,"foodbox2 contains %d item%s\n",{l,s})
|
||||
for i=1 to l do
|
||||
-- this.contents[i].eat() -- not supported, sorry!
|
||||
-- compiler needs some more type hints, such as:
|
||||
edible food = this.contents[i]
|
||||
food.eat()
|
||||
end for
|
||||
end procedure
|
||||
end class
|
||||
foodbox2 lunchbox2 = new()
|
||||
|
||||
class fruit2 extends edible
|
||||
procedure eat()
|
||||
printf(1,"mmm... %s\n",{this.name})
|
||||
end procedure
|
||||
end class
|
||||
fruit2 banana2 = new({"banana"})
|
||||
|
||||
class clay2
|
||||
string name = "common fletton"
|
||||
end class
|
||||
clay2 brick2 = new()
|
||||
|
||||
class drink extends edible
|
||||
procedure eat()
|
||||
printf(1,"slurp... %s\n",{this.name})
|
||||
end procedure
|
||||
end class
|
||||
drink milkshake = new({"milkshake"})
|
||||
|
||||
lunchbox2.add(banana2)
|
||||
try
|
||||
lunchbox2.add(brick2) -- triggers typecheck
|
||||
catch e
|
||||
printf(1,"%s line %d: %s\n",{e[E_FILE],e[E_LINE],e[E_USER]})
|
||||
end try
|
||||
lunchbox2.add(milkshake)
|
||||
lunchbox2.dine()
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
(class +Eatable)
|
||||
|
||||
(dm eat> ()
|
||||
(prinl "I'm eatable") )
|
||||
|
||||
|
||||
(class +FoodBox)
|
||||
# obj
|
||||
|
||||
(dm set> (Obj)
|
||||
(unless (method 'eat> Obj) # Check if the object is eatable
|
||||
(quit "Object is not eatable" Obj) )
|
||||
(=: obj Obj) ) # If so, set the object
|
||||
|
||||
|
||||
(let (Box (new '(+FoodBox)) Eat (new '(+Eatable)) NoEat (new '(+Bla)))
|
||||
(set> Box Eat) # Works
|
||||
(set> Box NoEat) ) # Gives an error
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#lang racket
|
||||
(module+ test (require tests/eli-tester))
|
||||
|
||||
;; This is all that an object should need to properly implement.
|
||||
(define edible<%>
|
||||
(interface () [eat (->m void?)]))
|
||||
|
||||
(define (generic-container<%> containee/c)
|
||||
(interface ()
|
||||
[contents (->m (listof containee/c))]
|
||||
[insert (->m containee/c void?)]
|
||||
[remove-at (->m exact-nonnegative-integer? containee/c)]
|
||||
[count (->m exact-nonnegative-integer?)]))
|
||||
|
||||
(define ((generic-box-mixin containee/c) %)
|
||||
(->i ([containee/c contract?])
|
||||
(rv (containee/c) (implementation?/c (generic-container<%> containee/c))))
|
||||
(class* % ((generic-container<%> containee/c))
|
||||
(super-new)
|
||||
(define l empty)
|
||||
(define/public (contents) l)
|
||||
(define/public (insert o) (set! l (cons o l)))
|
||||
(define/public (remove-at i)
|
||||
(begin0 (list-ref l i)
|
||||
(append (take l i) (drop l (add1 i)))))
|
||||
(define/public (count) (length l))))
|
||||
|
||||
;; As I understand it, a "Food Box" from the task is still a generic... i.e.
|
||||
;; you will specify it down ;; to an "apple-box%" so: food-box%-generic is still
|
||||
;; generic. food-box% will take any kind of food.
|
||||
(define/contract (food-box-mixin T%)
|
||||
(-> (or/c (λ (i) (eq? edible<%> i)) (implementation?/c edible<%>))
|
||||
(make-mixin-contract))
|
||||
(generic-box-mixin (and/c (is-a?/c edible<%>) (is-a?/c T%))))
|
||||
|
||||
(module+ test
|
||||
|
||||
(define integer-box% ((generic-box-mixin integer?) object%))
|
||||
(define integer-box (new integer-box%))
|
||||
|
||||
(define apple%
|
||||
(class* object% (edible<%>)
|
||||
(super-new)
|
||||
(define/public (eat)
|
||||
(displayln "nom!"))))
|
||||
|
||||
(define banana%
|
||||
(class* object% (edible<%>)
|
||||
(super-new)
|
||||
(define/public (eat)
|
||||
(displayln "peel.. peel... nom... nom!"))))
|
||||
|
||||
(define semolina%
|
||||
(class* object% () ; <-- empty interfaces clause
|
||||
(super-new)
|
||||
;; you can call eat on it... but it's not explicitly (or even vaguely)
|
||||
;; edible<%>
|
||||
(define/public (eat) (displayln "blech!"))))
|
||||
|
||||
;; this will take any object that is edible<%> and edible<%> (therefore all
|
||||
;; edible<%> objects)
|
||||
(define any-food-box (new ((food-box-mixin edible<%>) object%)))
|
||||
|
||||
;; this will take any object that is edible and an apple<%>
|
||||
;; (therefore only apple<%>s)
|
||||
(define apple-food-box (new ((food-box-mixin apple%) object%)))
|
||||
|
||||
(test
|
||||
;; Test generic boxes
|
||||
(send integer-box insert 22)
|
||||
(send integer-box insert "a string") =error> exn:fail:contract?
|
||||
|
||||
;; Test the food box that takes any edible<%>
|
||||
(send any-food-box insert (new apple%))
|
||||
(send any-food-box insert (new banana%))
|
||||
(send any-food-box insert (new semolina%)) =error> exn:fail:contract?
|
||||
|
||||
;; Test the food box that takes any apple%
|
||||
(send apple-food-box insert (new apple%))
|
||||
(send apple-food-box insert (new banana%)) =error> exn:fail:contract?
|
||||
(send apple-food-box insert (new semolina%)) =error> exn:fail:contract?
|
||||
(send apple-food-box count) => 1
|
||||
|
||||
;; Show that you cannot make a food-box from the non-edible<%> semolina cannot
|
||||
(implementation? semolina% edible<%>) => #f
|
||||
(new ((food-box-mixin semolina%) object%)) =error> exn:fail:contract?))
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
subset Eatable of Any where { .^can('eat') };
|
||||
|
||||
class Cake { method eat() {...} }
|
||||
|
||||
role FoodBox[Eatable] {
|
||||
has %.foodbox;
|
||||
}
|
||||
|
||||
class Yummy does FoodBox[Cake] { } # composes correctly
|
||||
# class Yucky does FoodBox[Int] { } # fails to compose
|
||||
|
||||
my Yummy $foodbox .= new;
|
||||
say $foodbox;
|
||||
|
|
@ -0,0 +1 @@
|
|||
Yummy.new(foodbox => {})
|
||||
18
Task/Constrained-genericity/Ruby/constrained-genericity.rb
Normal file
18
Task/Constrained-genericity/Ruby/constrained-genericity.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
class Foodbox
|
||||
def initialize (*food)
|
||||
raise ArgumentError, "food must be eadible" unless food.all?{|f| f.respond_to?(:eat)}
|
||||
@box = food
|
||||
end
|
||||
end
|
||||
|
||||
class Fruit
|
||||
def eat; end
|
||||
end
|
||||
|
||||
class Apple < Fruit; end
|
||||
|
||||
p Foodbox.new(Fruit.new, Apple.new)
|
||||
# => #<Foodbox:0x00000001420c88 @box=[#<Fruit:0x00000001420cd8>, #<Apple:0x00000001420cb0>]>
|
||||
|
||||
p Foodbox.new(Apple.new, "string can't eat")
|
||||
# => test1.rb:3:in `initialize': food must be eadible (ArgumentError)
|
||||
49
Task/Constrained-genericity/Rust/constrained-genericity.rust
Normal file
49
Task/Constrained-genericity/Rust/constrained-genericity.rust
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// This declares the "Eatable" constraint. It could contain no function.
|
||||
trait Eatable {
|
||||
fn eat();
|
||||
}
|
||||
|
||||
// This declares the generic "FoodBox" type,
|
||||
// whose parameter must satisfy the "Eatable" constraint.
|
||||
// The objects of this type contain a vector of eatable objects.
|
||||
struct FoodBox<T: Eatable> {
|
||||
_data: Vec<T>,
|
||||
}
|
||||
|
||||
// This implements the functions associated with the "FoodBox" type.
|
||||
// This statement is not required, but here it is used
|
||||
// to declare a handy "new" constructor.
|
||||
impl<T: Eatable> FoodBox<T> {
|
||||
fn new() -> FoodBox<T> {
|
||||
FoodBox::<T> { _data: Vec::<T>::new() }
|
||||
}
|
||||
}
|
||||
|
||||
// This declares a simple type.
|
||||
struct Banana {}
|
||||
|
||||
// This makes the "Banana" type satisfy the "Eatable" constraint.
|
||||
// For that, every declaration inside the declaration of "Eatable"
|
||||
// must be implemented here.
|
||||
impl Eatable for Banana {
|
||||
fn eat() {}
|
||||
}
|
||||
|
||||
// This makes also the primitive "char" type satisfy the "Eatable" constraint.
|
||||
impl Eatable for char {
|
||||
fn eat() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// This instantiate a "FoodBox" parameterized by the "Banana" type.
|
||||
// It is allowed as "Banana" implements "Eatable".
|
||||
let _fb1 = FoodBox::<Banana>::new();
|
||||
|
||||
// This instantiate a "FoodBox" parameterized by the "char" type.
|
||||
// It is allowed, as "char" implements "Eatable".
|
||||
let _fb2 = FoodBox::<char>::new();
|
||||
|
||||
// This instantiate a "FoodBox" parameterized by the "bool" type.
|
||||
// It is NOT allowed, as "bool" does not implement "Eatable".
|
||||
//let _fb3 = FoodBox::<bool>::new();
|
||||
}
|
||||
51
Task/Constrained-genericity/Sather/constrained-genericity.sa
Normal file
51
Task/Constrained-genericity/Sather/constrained-genericity.sa
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
abstract class $EDIBLE is
|
||||
eat;
|
||||
end;
|
||||
|
||||
class FOOD < $EDIBLE is
|
||||
readonly attr name:STR;
|
||||
eat is
|
||||
#OUT + "eating " + self.name + "\n";
|
||||
end;
|
||||
create(name:STR):SAME is
|
||||
res ::= new;
|
||||
res.name := name;
|
||||
return res;
|
||||
end;
|
||||
end;
|
||||
|
||||
class CAR is
|
||||
readonly attr name:STR;
|
||||
create(name:STR):SAME is
|
||||
res ::= new;
|
||||
res.name := name;
|
||||
return res;
|
||||
end;
|
||||
end;
|
||||
|
||||
class FOODBOX{T < $EDIBLE} is
|
||||
private attr list:LLIST{T};
|
||||
create:SAME is
|
||||
res ::= new;
|
||||
res.list := #;
|
||||
return res;
|
||||
end;
|
||||
add(c :T) is
|
||||
self.list.insert_back(c);
|
||||
end;
|
||||
elt!:T is loop yield self.list.elt!; end; end;
|
||||
end;
|
||||
|
||||
class MAIN is
|
||||
main is
|
||||
box ::= #FOODBOX{FOOD}; -- ok
|
||||
box.add(#FOOD("Banana"));
|
||||
box.add(#FOOD("Amanita Muscaria"));
|
||||
|
||||
box2 ::= #FOODBOX{CAR}; -- not ok
|
||||
box2.add(#CAR("Punto")); -- but compiler let it pass!
|
||||
|
||||
-- eat everything
|
||||
loop box.elt!.eat; end;
|
||||
end;
|
||||
end;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
type Eatable = { def eat: Unit }
|
||||
|
||||
class FoodBox(coll: List[Eatable])
|
||||
|
||||
case class Fish(name: String) {
|
||||
def eat {
|
||||
println("Eating "+name)
|
||||
}
|
||||
}
|
||||
|
||||
val foodBox = new FoodBox(List(new Fish("salmon")))
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class FoodBox(*food { .all { .respond_to(:eat) } }) { }
|
||||
|
||||
class Fruit { method eat { ... } }
|
||||
class Apple < Fruit { }
|
||||
|
||||
say FoodBox(Fruit(), Apple()).dump #=> FoodBox(food: [Fruit(), Apple()])
|
||||
say FoodBox(Apple(), "foo") #!> ERROR: class `FoodBox` !~ (Apple, String)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
protocol Eatable {
|
||||
func eat()
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
struct FoodBox<T: Eatable> {
|
||||
var food: [T]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
func foo<T: Eatable>(x: T) { }
|
||||
// although in this case this is no more useful than just "func foo(x: Eatable)"
|
||||
10
Task/Constrained-genericity/TXR/constrained-genericity-1.txr
Normal file
10
Task/Constrained-genericity/TXR/constrained-genericity-1.txr
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(defmacro define-food-box (name food-type : supers . clauses)
|
||||
(unless (subtypep food-type 'edible)
|
||||
(error "~s requires edible type, not ~s" %fun% food-type))
|
||||
^(defstruct ,name ,supers
|
||||
food
|
||||
(:method set-food (me food)
|
||||
(unless (typep food ',food-type)
|
||||
(error "~s: requires ~s object, not ~s" %fun% ',food-type food))
|
||||
(set me.food food))
|
||||
,*clauses))
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
(define-struct-clause :food-box (food-type :form form)
|
||||
(unless (subtypep food-type 'edible)
|
||||
(compile-error form "~s requires edible type, not ~s" :food-box food-type))
|
||||
^(food
|
||||
(:method set-food (me food)
|
||||
(unless (typep food ',food-type)
|
||||
(error "~s: requires ~s object, not ~s" %fun% ',food-type food))
|
||||
(set me.food food))))
|
||||
34
Task/Constrained-genericity/Wren/constrained-genericity.wren
Normal file
34
Task/Constrained-genericity/Wren/constrained-genericity.wren
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// abstract class
|
||||
class Eatable {
|
||||
eat() { /* override in child class */ }
|
||||
}
|
||||
|
||||
class FoodBox {
|
||||
construct new(contents) {
|
||||
if (contents.any { |e| !(e is Eatable) }) {
|
||||
Fiber.abort("All FoodBox elements must be eatable.")
|
||||
}
|
||||
_contents = contents
|
||||
}
|
||||
|
||||
contents { _contents }
|
||||
}
|
||||
|
||||
// Inherits from Eatable and overrides eat() method.
|
||||
class Pie is Eatable {
|
||||
construct new(filling) { _filling = filling }
|
||||
|
||||
eat() { System.print("%(_filling) pie, yum!") }
|
||||
}
|
||||
|
||||
// Not an Eatable.
|
||||
class Bicycle {
|
||||
construct new() {}
|
||||
}
|
||||
|
||||
var items = [Pie.new("Apple"), Pie.new("Gooseberry")]
|
||||
var fb = FoodBox.new(items)
|
||||
fb.contents.each { |item| item.eat() }
|
||||
System.print()
|
||||
items.add(Bicycle.new())
|
||||
fb = FoodBox.new(items) // throws an error because Bicycle not eatable
|
||||
10
Task/Constrained-genericity/Zkl/constrained-genericity-1.zkl
Normal file
10
Task/Constrained-genericity/Zkl/constrained-genericity-1.zkl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
class Eatable{ var v;
|
||||
fcn eat{ println("munching ",self.topdog.name); }
|
||||
}
|
||||
class FoodBox{
|
||||
fcn init(food1,food2,etc){
|
||||
editable,garbage:=vm.arglist.filter22("isChildOf",Eatable);
|
||||
var contents=editable;
|
||||
if(garbage) println("Rejecting: ",garbage);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
class Apple(Eatable){} class Nuts(Eatable){} class Foo{}
|
||||
FoodBox(Apple,"boogers",Nuts,Foo).contents.apply2("eat");
|
||||
Loading…
Add table
Add a link
Reference in a new issue