CDE
This commit is contained in:
parent
518da4a923
commit
764da6cbbb
6144 changed files with 83610 additions and 11 deletions
4
Task/Constrained-genericity/0DESCRIPTION
Normal file
4
Task/Constrained-genericity/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{{omit from|BBC BASIC}}
|
||||
'''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.
|
||||
4
Task/Constrained-genericity/1META.yaml
Normal file
4
Task/Constrained-genericity/1META.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category:
|
||||
- Type System
|
||||
note: Object oriented
|
||||
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.
|
||||
|
|
@ -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))
|
||||
21
Task/Constrained-genericity/D/constrained-genericity-1.d
Normal file
21
Task/Constrained-genericity/D/constrained-genericity-1.d
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
template IsEdible(T) {
|
||||
enum IsEdible = 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,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,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,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
|
||||
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")))
|
||||
Loading…
Add table
Add a link
Reference in a new issue