3 ms·
Every step of the scale will have to work with every other step of the scale. Does every step handle and allocate memory the same way? What about pointers? C/C+
by FLUX-YOU 10y ago
Every step of the scale will have to work with every other step of the scale. Does every step handle and allocate memory the same way? What about pointers? C/C++ interop? Does each one interact with the operating system the same way? How does a thread from one scale interact with objects from another scale? That's a lot to ask for something that's just going to be a prototyping feature (or a mode that is never used in production). How do you even think in such a mode, and is that easily teachable to other people from either background?
- nradov 10y agoThe simplest approach would be to take a dynamically typed language, like Python or something, and then add a full range of scalable type annotations that could be checked by the compiler (or a separate static analysis tool). The runtime system wouldn't have to change much, except perhaps to make the type annotations available through a reflection API. C/C++ interop and OS interactions are separate issues mostly orthogonal to type systems. Teaching would probably start without using the type annotations for simplicity. Let the students get something working first with basic dynamic code. Then teach the type annotations and reasons for using them in more advanced courses.
- raiph 10y agoThe Perl 6 student begins: sub add(\number1, \number2) { number1 + number2 } If you call `add` with simple numbers it works: say add(1, 2) # 3 Other types of number too: say add(0.1, 0.2) == 0.3 # True It works even for newbie definitions of "number": say add('0.1', '0.2') == '0.3' # True A sufficiently determined newbie can of course break `add`: say add('foo', 'bar') == 'waldo' The program stops with a suitable error message ("Cannot convert string to number ..."). ---- The student moves on to a more advanced course... ---- Type annotations are introduced: sub add(Numeric \number1, Numeric \number2) { number1 + number2 } Everything still works as expected: say add(1, 2) # 3 But we get better error checking: say add('foo', 'bar') == 'waldo' This generates a compile-time type-checking error ("Calling add(Str, Str) will never work with declared signature (Numeric \int1, Numeric \int2)"). So, reason 1 for using types: get type-checking that catches errors at compile-time. You can use native types for closer-to-the-metal speed (compact representations, no automatic overflow checking, etc.): sub add(num64 \number1, num64 \number2) { number1 + number2 } `num64` corresponds to C's double float datatype representation. This sub will likely outperform the versions of `add` that do not have natively typed parameters. A third reason for explicit types is to take advantage of C interop: use NativeCall; sub add(int32, int32) returns int32 is native("calculator") { * } If you've got a local C library (called "libcalculator.so" or somesuch) then this: say add(1,2) will call the function with the symbol name `add` in that library. And so on.