updating examples; stricter Iterable interface
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 15 Jan 2022 16:32:25 +0000 (10:32 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 15 Jan 2022 16:32:25 +0000 (10:32 -0600)
core/container/iter.onyx
examples/11_map.onyx
examples/22_interfaces.onyx

index 09d6bcc539415ed687a7ce8305f0d460af8055b4..54fc23e07cc787f29dce379c4015f91a79a4b044 100644 (file)
@@ -5,8 +5,9 @@ use package core.intrinsics.onyx { __zero_value }
 
 as_iterator :: #match {}
 
+#local __iterable_test :: macro (i: Iterator($V)) {}
 Iterable :: interface (t: $T) {
-    as_iterator(t);
+    as_iterator(t) |> __iterable_test();
 }
 
 close :: (it: Iterator($T)) {
index 80b25e694535d2dc17568e96452401183bceb2ec..cc75c9fab69fb940c4e988c66015503aaf2e6252 100644 (file)
@@ -44,17 +44,4 @@ main :: (args: [] cstr) {
 
     println(map.has(^ages, "Dwight"));
     println(map.has(^ages, "Michael"));
-
-
-
-    // Not now nor ever will Onyx support an "interface" concept to say
-    // which types can do which things. One thing that Onyx does have
-    // however is explicit overloaded procedures. They are talked about
-    // more in 14_overloaded_procs.onyx. For our purposes right now, we
-    // just need to know that Map uses an overloaded procedures to
-    // achieve its implementation, map.hash_function.
-    // To make Map work with any new datatype you come up with, simply
-    // define an overload for map.hash_function and the '==' operator.
-    // If you want to see what this looks like, take a look at
-    // tests/aoc-2020/day17.onyx in this repository.
 }
index 2dedc83a8e540726d1c15e643bf164ee25d4e144..d2dcbd9e7bf1b2b59ed5ae565a3ab10a4a3198d2 100644 (file)
@@ -24,8 +24,16 @@ add_example :: () {
     // but after programming with it for a while, I think it is the right
     // syntax.
 
-    CanAdd :: interface (T: type_expr) {
-        T + T;
+    // Interfaces are written like polymorphic functions, except *every* parameter
+    // must introduce a single polymorphic variable. Effectively this means for
+    // every parameter you get two things: the parameter value, and the parameter
+    // type. The body of the interface specifies a list of expressions that must
+    // be legal in order for the parameters to meet the interface. If any of the 
+    // expressions do not type check correctly, then the set of parameters does not
+    // satisfy the interface.
+
+    CanAdd :: interface (t: $T) {
+        t + t;
     }
 
     // To use this interface, you must write a "where" clause for a procedure or
@@ -51,14 +59,14 @@ add_example :: () {
 
 // These have to be defined out here because #operator and #match are only allowed
 // as top level expressions currently.
-NumberLike :: interface (T: type_expr) {
-    // The constraints here are a little stricter than before, as you must be
-    // able to cast the result of these operations back to the original type.
-    // This effectively means that T + T must be the same type as (or a compatible
-    // type of) T.
-    cast(typeof T) (T + T);
-    cast(typeof T) (T - T);
-    cast(typeof T) (T * T);
+NumberLike :: interface (t: $T) {
+    // The constraints here are a little stricter than before. This syntax
+    // allows you to specify the expected type of the expression. If the type
+    // of the expression and the type after the arrow do not match, then the
+    // interface check fails.
+    {t + t} -> T;
+    {t - t} -> T;
+    {t * t} -> T;
 }
 
 // Here, Vector2 has the type constraint of NumberLike for T. This constraint
@@ -80,7 +88,7 @@ struct_example :: () {
 
     // This will generate an error because the dot product definition of
     // multiplication of two Vector2(f32) results in a f32, which cannot
-    // be casted to a Vector2(f32).
+    // is not Vector2(f32).
     // v2 := Vector2(Vector2(f32)).{};
     // println(v2);
 }
@@ -93,8 +101,8 @@ overloaded_procedure_example :: () {
     // when the are combined with overloaded procedures.
 
     // Take this example. Here is the same CanAdd interface from before.
-    CanAdd :: interface (T: type_expr) {
-        T + T;
+    CanAdd :: interface (t: $T) {
+        t + t;
     }
 
     // This overloaded procedure has two procedures that have almost identical