What Ada (and Rust) calls generics is very different -- it is like template functions in C++.
In those languages the version of the function that is selected is based on the declared type of the arguments.
In CLOS, Dylan, Julia the version of the function that is selected is based on the runtime type of the actual arguments.
Here's an example in Dylan that you can't do in Ada / Rust / C++ / Java.
define method fib(n) fib(n-1) + fib(n-2) end; define method fib(n == 0) 0 end; define method fib(n == 1) 1 end;
The Julia version is slightly more complex.
fib(n) = fib(Val(n)) fib(::Val{n}) where {n} = fib(n-1) + fib(n-2) fib(::Val{0}) = 0 fib(::Val{1}) = 1 println(fib(30))
This of course is just a function with a single argument, but you can do the same thing across multiple arguments.
define method ack(m, n) ack(m-1, ack(m, n-1)) end; define method ack(m == 0, n) n+1 end; define method ack(m, n == 0) ack(m-1, 1) end;
As you can see from my comment history, I am quite aware of CLOS, Lisp variants and Dylan.
reply
What Ada (and Rust) calls generics is very different -- it is like template functions in C++.
In those languages the version of the function that is selected is based on the declared type of the arguments.
In CLOS, Dylan, Julia the version of the function that is selected is based on the runtime type of the actual arguments.
Here's an example in Dylan that you can't do in Ada / Rust / C++ / Java.
The `n == 1` is actually syntactic sugar for the type declaration `n :: singleton(1)`.The Julia version is slightly more complex.
This is perhaps a crazy way to write `fib()` instead of a conventional `if/then/else` or `?:` or switch with a default case, but kinda fun :-)This of course is just a function with a single argument, but you can do the same thing across multiple arguments.