Data commit

This commit is contained in:
Ingy döt Net 2023-07-01 11:58:00 -04:00
parent 7387c8f97b
commit cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions

View file

@ -0,0 +1,5 @@
---
category:
- Type System
from: http://rosettacode.org/wiki/Constrained_genericity
note: Object oriented

View 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.

View 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;

View file

@ -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.

View 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;
}

View file

@ -0,0 +1,4 @@
interface IEatable
{
void Eat();
}

View file

@ -0,0 +1,6 @@
using System.Collections.Generic;
class FoodBox<T> where T : IEatable
{
List<T> food;
}

View file

@ -0,0 +1,7 @@
class Apple : IEatable
{
public void Eat()
{
System.Console.WriteLine("Apple has been eaten");
}
}

View file

@ -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());
}
}
}

View file

@ -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))

View file

@ -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])

View 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
}

View 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
}

View 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
}

View file

@ -0,0 +1,10 @@
deferred class
EATABLE
feature -- Basic operations
eat
-- Eat this eatable substance
deferred
end
end

View file

@ -0,0 +1,14 @@
class
APPLE
inherit
EATABLE
feature -- Basic operations
eat
-- Consume
do
print ("One apple eaten%N")
end
end

View file

@ -0,0 +1,14 @@
class
PEAR
inherit
EATABLE
feature -- Basic operations
eat
-- Consume
do
print ("One pear eaten%N")
end
end

View file

@ -0,0 +1,10 @@
class
FOOD_BOX [G -> EATABLE]
inherit
ARRAYED_LIST [G]
create
make
end

View file

@ -0,0 +1 @@
my_apple_box: FOOD_BOX [APPLE]

View file

@ -0,0 +1 @@
my_refrigerator: FOOD_BOX [EATABLE]

View file

@ -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

View file

@ -0,0 +1 @@
-- my_apple_box.extend (one_pear)

View file

@ -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()]

View 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

View 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

View file

@ -0,0 +1,3 @@
type eatable interface {
eat()
}

View file

@ -0,0 +1 @@
type foodbox []eatable

View file

@ -0,0 +1,6 @@
type peelfirst string
func (f peelfirst) eat() {
// peel code goes here
fmt.Println("mm, that", f, "was good!")
}

View 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()
}

View file

@ -0,0 +1,2 @@
class Eatable a where
eat :: a -> String

View file

@ -0,0 +1 @@
data (Eatable a) => FoodBox a = F [a]

View file

@ -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"

View file

@ -0,0 +1,2 @@
instance Eatable Double where
eat d = "I'm eating " ++ show d

View file

@ -0,0 +1,2 @@
class Food a where
munch :: a -> String

View file

@ -0,0 +1,2 @@
instance (Food a) => Eatable a where
eat x = munch x

View file

@ -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

View 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
)

View file

@ -0,0 +1,4 @@
coclass'Apple'
eat=:3 :0
smoutput'delicious'
)

View 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

View file

@ -0,0 +1,4 @@
interface Eatable
{
void eat();
}

View file

@ -0,0 +1,6 @@
import java.util.List;
class FoodBox<T extends Eatable>
{
public List<T> food;
}

View file

@ -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)"

View file

@ -0,0 +1,3 @@
public class Test{
public <T extends Eatable> void bar(){ }
}

View file

@ -0,0 +1 @@
test.<EatableClass>bar();

View file

@ -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)

View file

@ -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!")
}

View file

@ -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 >; } ));
}

View file

@ -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 >; } ));
}

View file

@ -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();

View 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)

View file

@ -0,0 +1,4 @@
module type Eatable = sig
type t
val eat : t -> unit
end

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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>;
}
}

View file

@ -0,0 +1,3 @@
@protocol Eatable
- (void)eat;
@end

View file

@ -0,0 +1,2 @@
@interface FoodBox<T : id<Eatable>> : NSObject
@end

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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()

View file

@ -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

View file

@ -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?))

View file

@ -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;

View file

@ -0,0 +1 @@
Yummy.new(foodbox => {})

View 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)

View 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();
}

View 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;

View file

@ -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")))

View file

@ -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)

View file

@ -0,0 +1,3 @@
protocol Eatable {
func eat()
}

View file

@ -0,0 +1,3 @@
struct FoodBox<T: Eatable> {
var food: [T]
}

View file

@ -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)"

View 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))

View file

@ -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))))

View 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

View 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);
}
}

View file

@ -0,0 +1,2 @@
class Apple(Eatable){} class Nuts(Eatable){} class Foo{}
FoodBox(Apple,"boogers",Nuts,Foo).contents.apply2("eat");