@BHX: The only quirk in Java I know of is that generics are not part of the type system, and the only C++ quirk I know of is that you cannot extend a class that virtually private inherits another class. With JavaScript, the quirks are in-your-face.
@LB Quirks of a language change from user to user. Somethings you might consider quirks other don't and vice versa. It's all in the eye of the beholder.
IF you're worried about typing and the value of each bit, then you're not using the weak-typed languages properly. They aren't meant to pack bit-specific protocols wrt endians and supporting masking properly. They are meant as higher level languages where supporting such things introduces a level of definition which complicates the user experience to a degree that destroys the point of the language.
Weak typing is a feature that someone has had to work hard to achieve, which supposedly makes someone else's life easier. C++ vs Java is really just about syntax differences. When I went from C++ to Lua, I had to ignore everything I knew about defining variables. Only when I was able to let that go and learn to not depend on the individual bits and types, was I able to embrace what it really had to offer.
I don't care about the individual bits, in fact I never think of them. What throws me off is that there is no compile-time/parse-time safety against writing code that looks right but is completely nonsense.
It is true that this is something you loose with such languages. This is why I brought up testing. ( and linked to https://github.com/Lowest0ne/python_test_prime ). The tests I wrote don't check for type safety, but they could. I just know that I will get the responses I expect from an is_prime method.
Open the ActionMailer folder and inside is a folder named test ( most all of the folders have a test folder ). Inside the test folder are hundreds and hundreds of tests to make sure that all of the code works as intended.
If you make a pull request to Rails, the commit is run through TravisCI, which will run all of the tests. If the tests pass, then they know it is a safe commit to merge. If you wanted to add a feature to Rails, first you would write a failing test, and then write code until the test passed.
So there isn't compile time safety, but we know that things are working because the tests pass.
That sounds like a rather trial-and-error approach, but I guess it depends on how fine grained the tests are. I can't say for sure, but I would feel like statically typed language would require less tests - would they?
I don't know if you looked through the commits at my repo. Errors.txt contains the error messages I got along the way. An error message might be "method not defined", so I go define the method. The next error would be "method doesn't take 1 argument", well, it should, so I go make it take one argument. Eventually, the tests pass and my code works.
less tests
Compiling does not find logic errors, but tests do. Good tests will also find type errors.
If you are writing in Python, you should check out doctest, which I believe is Python core. Doctest is a way of writing code comments that are also tests.
The best feeling is when you find a bug in your program and you write a test that exploits that bug. When you get that test passing you know that the bug is gone.
But something trivial like if ( x = 1 ) will not be found.
But testing can't prove the absence of type errors
Sure you can. I know Ruby better than Python, so...
1 2 3 4 5 6 7 8 9
// prime.rb
class Prime
def self.is_prime?( number )
raise TypeError, "Argument is not Fixnum" unless number.is_a? Fixnum
end
end
1 2 3 4 5 6 7 8 9 10 11 12
// prime_spec.rb ( using rspec for test )
require 'prime'
describe Prime do
it 'raises type errors'do
expect{ Prime::is_prime?( "string" ) }.to raise_error( TypeError )
expect{ Prime::is_prime?( 1.23 ) }.to raise_error( TypeError )
expect{ Prime::is_prime?( nil ) }.to raise_error( TypeError )
end
end
Tests pass.
Edit: Or if you're lazy and embrace this sort of thing:
1 2 3 4 5 6 7
it 'raises type errors'do
[ "string", 1.23, nil, TypeError ].each do | type |
expect{ Prime::is_prime?( type ) }.to raise_error( TypeError )
end
end
Sure it does. Doing something nonsensical like trying to rasterize a database connection is a logic error.
Not according to what I learned in college and every book I've ever read. Compiling (the compiler) only find syntax errors. Logic errors usually only show themselves in the form of runtime errors.
Compiling does not find logic errors, but tests do. Good tests will also find type errors.
helios wrote:
Sure it does. Doing something nonsensical like trying to rasterize a database connection is a logic error.
Me wrote:
Not according to what I learned in college and every book I've ever read. Compiling (the compiler) only find syntax errors. Logic errors usually only show themselves in the form of runtime errors.
@LB
They were talking about compiling (which python and lua can be compiled and doing so makes my statement still true). Their remarks had nothing to do with interpreted languages.
But something trivial like if ( x = 1 ) will not be found.
That's the Nirvana fallacy. Dynamic compilers are capable of even less checking.
Sure you can.
No, you can't. Testing is incapable of proper "proving" in the mathematical sense, except in those rare cases where the entire input space is small enough to test completely.
Compiling (the compiler) only find syntax errors. Logic errors usually only show themselves in the form of runtime errors.
Type errors are errors at the semantic, not syntactic level. std::cin.read((Banana)banana) is a well-formed but type-incorrect subprogram.
Like LB said, if in a dynamic language a type error causes a run time error, then type errors are logic errors. It just so happens that the compilers for some types of languages will accept programs with type errors, while compilers for some other types of languages will reject them. That doesn't change the nature of type errors.