in python this is an error:
>>> i = 10
>>> s = "20"
>>> s+=i;
TypeError: cannot concatenate 'str' and 'int' objects
>>> i+=s;
TypeError: unsupported operand type(s) for +=: 'int' and 'str'It should never happen in production - there should be a test that proves this.
In Common Lisp, the SBCL compiler would be such an example:
* (defun foo () (let ((i 10) (s "20")) (concatenate 'string s i)))
; in: DEFUN FOO
; (CONCATENATE 'STRING S I)
;
; caught WARNING:
; Derived type of I is
; (VALUES (INTEGER 10 10) &OPTIONAL),
; conflicting with its asserted type
; SEQUENCE.
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
FOO
*my preferred language is pike, which is a strong and declarative typed language (declarative typing is the term i prefer since not everyone defines static typing the same way, and some statically typed languages are weak, like this example here)
pike does catch type errors at compile time, but behaves like a strong dynamic typed language at runtime.
i understand that python and rubys optional types now allow for something similar.
I'd say that while there's certainly a ton of purely dynamically-typed code out there, there's also a current reversal of the trend, with static and gradual typing coming back in vogue. Python has fully-supported type annotations, and Typescript is the trendy new way of writing JS. Facebook has ReasonML and Hack/PHP 7. Go and Rust, the current "cool kid" languages, are fully statically typed.
I think that the bad taste left in people's mouths by "enterprise" Java and its 30-character type names is fading, and that we'll see a few years of static types. Then of course the cycle will repeat itself, as is tradition.
I'm saying this as an experienced dev, please consider from this and others that you may be wrong, and avoid the trouble we've had.
Or not. Everyone has to find their own way.
I continue to use python without type-hints because of know of no other similar languages with type-hints that are as popular.
string s = 10; s += 20;
What I define is an operation within a string. The context is defined by the recipient variable. In the same way:
int i = 20; i += "30";
The variable "i" defines an integer context and therefore string 30 is considered in this case as a number.
As a source code reader I would much prefer to see at least a keyword or function call to make the casting explicit.
string s = cast 10; s += cast 20;
(I had the same reaction as the parent and think the language looks really cool otherwise)
i = int(s)+10;
Each type can be used as a "function" to create the object you like, which is basically what a cast is...
I don't deal with a lot of ad-hoc data, but even when I do, that data usually needs strict validation, as it tends to not be very clean. Having things silently convert hides this and while it may make the code simpler, that code should have validation anyway, so it really won't be any more work in the long run (for me). Slight errors in data cause billion dollar bugs, after all. Maybe not in NLP though, so, again, we have different use cases.
But that's just me and obviously my priorities differ from yours. In any case, congratulations on building this, that's quite an achievement.
Nice!
Perl does this and it's a lot cleaner IMO. Whenever you see a "+" you can consider it an explicit numeric conversion of both arguments: https://codespeaks.blogspot.com/2007/09/ruby-and-python-over...
In fact, there is no dedicated numeric conversion operator in perl. The canonical "operator" for this is called the "0+" operator.
Python-style dynamic-typing and strictness is sort of the worst-of-both-worlds approach. Many times I've lost rarely-seen log messages to "cannot concatenate 'str' and 'int' objects" errors.
I'm building one too in Rust and there exist a very nice concept:
https://doc.rust-lang.org/std/convert/trait.From.html
Is the first time I see a blessed way into a lang to define conversions.
For example, to parse strings into int you need to say (in pseudo-code):
convert::From(String) -> Int //Or better convert::TryFrom
and suddenly you get the way to convert to strings into ints EVERYWHERE.Is amazing.
The key here is that is for much more than just basic stuff. You can do a lot of very convoluted things here, like Auto-Convert a vector of ints into a Zip compressed stream in one go.
----
The second things required is how avoid the boilerplate when dealing with data. If I read a file and need a lot of parsing and validation and need to be relaxed about this... how about the same thing between eager and lazy?
- Have "strict" by default and need to manually do
1->Str + "hello" + today->Str + ...
calls- Have a "auto-convert" when need to chain a lot of steps:
auto {
1 + "hello" + today + ...
}
this is nice because you can see where the " big dirty vicious beasts full of mistakes and traps" are in your code!In this example, I implement a join that takes a vector and transforms it into a string.
//type declaration
<joining:: vector -> string>
//The function itself
<joining(v) = x | x <- v>
println(joining(['a'..'z']));