Java is a statically typed language which couldn't care less for type safety



  • Well, what IDE do you use for python, and how does the autocomplete/typo underlining/refactoring/like 90% of the stuff that I love about strongly-typed languages tooling stack up?



  • @Buddy said:

    Well, what IDE do you use for python, and how does the autocomplete/typo underlining/refactoring/like 90% of the stuff that I love about strongly-typed languages tooling stack up?

    It's definitely possible to do autocomplete, bad-syntax underlining, and refactoring in Python (take a look at something such as Wing IDE) -- but let me put it this way -- I work in a statically compiled language these days (C++), and my tools (VS) don't support refactoring AIUI.

    I generally don't use an IDE for Python these days, anyhow.



  • @Masaaki_Hosoi said:

    Dynamic languages are kinda cool, at least on the outset, and have their uses.But goddamn they can be such a pain to work with, and I highly prefer languages with strong types. Compile-time type safety FTW.

    That's a false dichotomy.

    You could design a dynamic language that is tightly-integrated with Intellisense-like features to catch the vast vast majority of type errors at "write-code" time. Look at TypeScript, for example.



  • @tarunik said:

    Define "good enough tools" -- I've used VS before, and use it at my current job -- and sure as heck don't know how the heck you could Edit and Continue on a C++ header file!

    VS is a good tool. C++ is a shitty one. You're halfway there.



  • @blakeyrat said:

    That's a false dichotomy.

    You could design a dynamic language that is tightly-integrated with Intellisense-like features to catch the vast vast majority of type errors at "write-code" time. Look at TypeScript, for example.

    Yeah, but the problem is that with a dynamically typed language it's nearly impossible to properly determine the type of a variable before runtime. The only reason Typescript has those features, for instance, is because they bolted on type information as a language feature, and even so it doesn't work 100% of the time.



  • Right; but my point is you're conflating "hasn't been done yet" with "can't be done at all". Don't do that.


  • Discourse touched me in a no-no place

    @Masaaki_Hosoi said:

    the problem is that with a dynamically typed language it's nearly impossible to properly determine the type of a variable before runtime.

    Hmm, and there I was, working on code that does just that. Still deeply experimental though, and has plenty of spots where it's currently broken by its incompleteness, so no link to it at this time. 😄

    To be fair though, the code is still designed to work at runtime. It's a JIT engine that I'm working on, not a pre-compilation engine.



  • @blakeyrat said:

    Right; but my point is you're conflating "hasn't been done yet" with "can't be done at all". Don't do that.

    I didn't, though. I didn't say anything like that at all.
    When I said "Compile-time type safety FTW" I never meant that dynamic languages will never have that feature. But the truth is they don't yet have that feature (not to the same extent, anyway), whereas statically typed languages do.



  • @dkf said:

    Hmm, and there I was, working on code that does just that. Still deeply experimental though, and has plenty of spots where it's currently broken by its incompleteness, so no link to it at this time. 😄

    To be fair though, the code is still designed to work at runtime. It's a JIT engine that I'm working on, not a pre-compilation engine.

    Keyword nearly I suppose

    EDIT: Not unlike the difference between "dead" and "mostly dead" ;)


  • Discourse touched me in a no-no place

    @Masaaki_Hosoi said:

    Keyword nearly I suppose ;)

    It depends on what you analyse the dynamic language down into. If you can determine what the operations that yield or require numeric (or other atomic) values are, you can do a decent translation into something like LLVM IR, and thence to machine code. Of course, you can do it by spraying type annotations over everything, but with most code you can deduce the types through the operations. I think. (I've succeeded with simple cases like computing trigonometric functions from first principles, where we can get close to the same speed as doing it in C++, but extending to a full production language is non-trivial. This is definitely a crazy out-there project! 😃)



  • @dkf said:

    It depends on what you analyse the dynamic language down into. If you can determine what the operations that yield or require numeric (or other atomic) values are, you can do a decent translation into something like LLVM IR, and thence to machine code. Of course, you can do it by spraying type annotations over everything, but with most code you can deduce the types through the operations. I think. (I've succeeded with simple cases like computing trigonometric functions from first principles, where we can get close to the same speed as doing it in C++, but extending to a full production language is non-trivial. This is definitely a crazy out-there project! 😃)

    Hehe, I've written my own compiler for a custom language somewhat recently. Or, well, sorta - actually it takes the custom language and spits out auto-generated C code (this being for an embedded platform). It has some amount of compile-time type awareness, but I got lazy (it was for my own purposes), so the type awareness completely falls over when you reference external C or H files. For that matter, it doesn't have actual type safety either (it only uses type information when accessing class or struct fields) >.>
    I couldn't even begin to imagine the amount of work involved in adding type safety to a dynamic language (at compile time anyway - runtime is a fair bit easier methinks)



  • @tarunik said:

    I generally don't use an IDE for Python these days, anyhow.

    I knew it.

    @tarunik said:

    I work in a statically compiled language these days (C++), and my tools (VS) don't support refactoring AIUI.

    Yeah, I've used VC++ too, and I know how infinitely worse it is than C# or Java. But if you're allowed to discard js as a bad exemplar of dynamic languages, surely we can do the same with C++.

    @blakeyrat said:

    You could design a dynamic language that is tightly-integrated with Intellisense-like features to catch the vast vast majority of type errors at "write-code" time. Look at TypeScript, for example.

    This is the worst “uh, actually” post I've ever seen from you. Firstly, sure you could get good tooling for a dynamic language, but it's inherently harder to do because the entire point of dynamic typing is that you don't know what type of object something is until the code actually runs. Secondly, TypeScript isn't even a valid counter-example, since ‘strong types’ and ‘compile-time type safety’ represent TypeScript's entire claim to fame.



  • @Buddy said:

    This is the worst “uh, actually” post I've ever seen from you.

    It isn't one.

    @Buddy said:

    Firstly, sure you could get good tooling for a dynamic language, but it's inherently harder to do because the entire point of dynamic typing is that you don't know what type of object something is until the code actually runs.

    A lot of worthwhile pursuits are difficult.

    @Buddy said:

    Secondly, TypeScript isn't even a valid counter-example, since ‘strong types’ and ‘compile-time type safety’ represent TypeScript's entire claim to fame.

    And therefore...?

    You forgot to get to the part where you actually explain why TypeScript isn't a valid counter-example.



  • Because the fact that a dynamic language can be upgraded with the addition of static types isn't an argument in favor of dynamic typing.


  • FoxDev

    Nor is it an argument against 😛



  • Yes it... is? Whatever.



  • When was the last time you used C#'s dynamic type?


  • FoxDev

    ASP.NET MVC ViewBags are dynamic, and I use them a lot at work 😛



  • Because all that stuff's just a workaround for the inherent flimsiness of dynamic typing? I mean, what is the actual advantage of dynamic typing in the first place?



  • @Buddy said:

    Because all that stuff's just a workaround for the inherent flimsiness of dynamic typing? I mean, what is the actual advantage of dynamic typing in the first place?

    Duck typing's kinda cool. Then again, interfaces.


  • I survived the hour long Uno hand

    @Masaaki_Hosoi said:

    Duck typing

    I like the idea of duck typing, but I am growing suspicious thanks to one concern: what if it claims to quack but instead does something entirely different? Is it still a duck?



  • Sure it's nice having the freedom to be lazy and halfass some times, but when the time comes to polish everything up and cover the edge cases, if you're using a language that doesn't have static typing everything's gonna be ten times harder than it needs to be.


  • :belt_onion:

    You can do that, and some things will be beautiful - but other people will use that power to create horrors



  • Microsoft hasn't, but MonoDevelop has the "Immediate Window" pad at runtime (though not at design time). Since Roslyn is open source, extending it to design time should be easily possible.



  • @Buddy said:

    I mean, what is the actual advantage of dynamic typing in the first place?
    1. Objects can easily become "expandos", their shape changing as needed both during app evolution (e.g. REPL) and as the final product (application A can stuff A-specific data into objects from library B and expect them to survive). Extension methods and dependency properties, for example, fill in the gaps in languages that support them, but in both cases you're relying on some external oracle to produce the extra information when presented with a plain object, rather than the extra information being part of the object.

    1. Duck typing. As long as the "shape" of an object is correct, you can pass it anywhere that expects that shape, no bookkeeping required. This can be useful when dealing with someone else's code, especially when you have objects that can do what you want but don't have the correct shape for some reason; rather than having to wrap them and compose/decompose and other mess, just use their expando-ness to fit them to the right shape.

    2. Proxy objects. Let's say you're using local proxies for some remote service. Would you rather (use a tool to) create a class that explicitly redefines each of the remote endpoints in the local language and include code at each endpoint for doing the proxying? Or would you rather have one function that can proxy any endpoint, and have that function be called by any name the local code uses, especially the names of the remote endpoints? (And you can use the information that would have made the statically-typed proxy to provide IntelliSense and warnings/errors, so you don't give that up.)


  • Discourse touched me in a no-no place

    @Yamikuronue said:

    what if it claims to quack but instead does something entirely different? Is it still a duck?

    The answer to that is simple: no, it is not a duck.

    A proper interface specification should define not just the interface syntax of the calls (i.e., what arguments you pass in and what result you get) but also a definition of the semantics of the operations. Mathematically, the interface contract should be a model of the semantics that will act as a simulation of any conforming implementation. Like that, as long as what you're relying on as a client of the interface is that it behaves according to what the interface describes, everything will be fine.

    Lots of programmers don't seem to understand this, yet it's so simple…


  • Discourse touched me in a no-no place

    @Buddy said:

    when the time comes to polish everything up and cover the edge cases

    When that time comes, most programmers just do the equivalent of filling it up with some cheap plaster and then putting painted wallpaper over it to hide the cracks.



  • @RaceProUK said:

    Seems an odd choice; they could have switched to Lua or something (I think the Source engine uses Lua for scripting?)

    @dkf said:

    I believe that varies by game.

    If you're talking about what is primarily* client-side scripting, then yes. Left 4 Dead and later allow client-side scripting. Most Valve-made games use Squirrel, but as @blakeyrat already pointed out, DOTA2 uses LUA.

    However, if you're talking about the server side, the only interface available on all games is the Valve Server Plugin, a C++ API.

    That is, unless you write a script for an existing VSP that embeds its own scripting language. Eventscripts embeds Python while SourceMod embeds their own variant of Pawn called SourcePawn.

    *Left 4 Dead 2 also uses it in the Expanded Mutation System, which runs on the server-side. DOTA2 is also an exception to this, but DOTA2 is special as Valve hasn't released an official server for it.



  • @TwelveBaud said:

    Duck typing. As long as the "shape" of an object is correct, you can pass it anywhere that expects that shape, no bookkeeping required. This can be useful when dealing with someone else's code, especially when you have objects that can do what you want but don't have the correct shape for some reason; rather than having to wrap them and compose/decompose and other mess, just use their expando-ness to fit them to the right shape.

    Java can do this and it doesn't use dynamic typing.


  • FoxDev

    @danixdefcon5 said:

    Java can do this and it doesn't use dynamic typing.

    How?



  • @RaceProUK said:

    How?

    Magic!



  • I just assumed he was talking about one of these:

    • implicit widening conversions
    • Programming against an interface instead of an explicit implementation.
    • Generics
    • At a stretch... Inversion of Control.

  • FoxDev

    None of which is dynamic programming


  • Discourse touched me in a no-no place

    @RaceProUK said:

    How?

    The reflection mechanism. You probably don't want to think about it very much…



  • I was going to reply to @RaceProUK's latest post, but I figured it'd be much easier to address directly.

    Dynamically typing has its downsides, too.

    1. Adding arbitrary data to an item can have its own special problems:
    • You've been adding library B specific things to application A objects for a while. You upgrade application A and suddenly start having issues with the data you were stuffing from Library B. What happened?
    • Well, turns out that Application A now has variables with the same name as the ones you were stuffing into it from Library B and one of them is clobbering the data from the other.
    1. Duck Typing ends up with all sorts of fun things. For instance:
    • In JavaScript, what does 9 + 8 + "7" equal? Personally, I don't know without testing. From the look of it, I'd think "177", but JS may decide that "7" is a number and make that 24 instead... or decide that all 3 are strings and have it be "987". Incidentally, after testing, "177" is the answer according to JSBin.
    • ...but then 0 == "0" is true. If you don't want it to be true, you have to use === instead.
    1. Proxy objects are a convenience not a necessity. For that matter, dealing with SOAP requests (the most likely one you're using if you're creating a proxy object), with PHP's SoapClient, you may still end up creating a class for them in order to match the appropriate XSD complextype...

  • FoxDev

    @dkf said:

    The reflection mechanism

    https://youtu.be/OK_YpGm1Fj4?t=16s



  • @powerlord said:

    Well, turns out that Application A now has variables with the same name as the ones you were stuffing into it from Library B and one of them is clobbering the data from the other.

    I'm pretty sure the dynamic camp's answer to this is "don't worry, it won't happen". Formally, they really mean "it costs more to prevent this situation than to deal with it". Whether or not you agree is pretty much what puts you in the static or dynamic camp.



  • @powerlord said:

    Duck Typing ends up with all sorts of fun things. For instance:

    • In JavaScript, what does 9 + 8 + "7" equal? Personally, I don't know without testing. From the look of it, I'd think "177", but JS may decide that "7" is a number and make that 24 instead... or decide that all 3 are strings and have it be "987". Incidentally, after testing, "177" is the answer according to JSBin.

    • ...but then 0 == "0" is true. If you don't want it to be true, you have to use === instead.


    I would argue those issues are orthogonal to both duck typing and dynamic typing. The possibility of either "177" or 24 being reasonable possible answers is a consequence of JS's weak typing, not duck typing. By contrast, Python is unquestionably duck typed, but that expression produces a TypeError in that language.

    Edit: C++ templates are an example of static duck typing, and template <typename A, typename B, typename C> foo(A a, B b, C c) { return a + b + c; } .... foo<int, int, std::string>(9, 8, "7"); will produce a type error as well. (Well, actually you'd get a syntax error for leaving out foo's return type, but I left that out just for simplicity.)

    Edit again: Actually I guess it's not entirely orthogonal to dynamic typing, because the fact that a string could be converted to an integer is a property of the string. So if you had, say, "7" + 7 evaluate to 14 but "a" + 7 evaluate to "a7", that could only happen in a dynamically typed language.1 Nevertheless, if you knew that your dynamic language was strongly typed then the confusion wouldn't arise.

    1 Yeah yeah, "what about dependent types." Shut up. :-)


  • Discourse touched me in a no-no place

    @Jaime said:

    I'm pretty sure the dynamic camp's answer to this is "don't worry, it won't happen". Formally, they really mean "it costs more to prevent this situation than to deal with it". Whether or not you agree is pretty much what puts you in the static or dynamic camp.

    It also really doesn't happen all that much once you get away from the moronic cases (such as everything assuming it can define a global function called Eval()…) and that's a relatively simple application of any namespacing technique.


  • Discourse touched me in a no-no place

    @EvanED said:

    a consequence of JS's weak typing

    It's at least in part a consequence of the overloading of the + operator to do two rather different things (addition and concatenation) while supporting automatic type casting between the two. Oh well, at least JS defines the evaluation order, which makes the result a predictable WTF…



  • Mother Belgium JAVA. I HATE YOU, you POS BELGIUM



  • @Jaime said:

    "don't worry, it won't happen".

    But how do you know what's in a variable?

    I mean, you can't even determine with some sort of intelligent crawler. The answer may be in a file you don't even have access to.

    And even if you do, the most it will be able to tell is what the source code says has ever been in it, based on whatever assignments it can parse out.



  • @xaade said:

    But how do you know what's in a variable?

    You don't, not without running an inspection function. That's why JS frameworks are full of code that looks like this:

    if (typeof handler === 'function') { 
      return handler.call(context, arg1, arg2); 
    } else {
      return handler;
    }
    
    

    I prefer static to dynamic languages. But, I understand someone deciding that the work it takes to handle the bugs that come up due to the lack of strong typing is less than the work required to implement strong typing. I don't agree with them, but they have a rational thought process that I can follow.



  • @Jaime said:

    work required to implement strong typing

    Something an app developer never does.

    @Jaime said:

    work it takes to handle the bugs that come up due to the lack of strong typing

    Something an app developer would have to always do. And if it's compiled, they are stuck without any reasonable way prior to runtime to determine this at all.



  • Hey, that's why I'm on the same side you are. But, claiming the other side is insane is no way to debate the issue.



  • It only makes sense because they changed their order of priority for debugging.

    Something screwed up with this variable, exception thrown. Maybe I put the wrong type in it, or expected the wrong type from it.

    And of course there's what I do, which is basically app Hungarian notation, which is basically the same amount of app work done to implement strong typing.

    nameCounter
    nameListOfCounters

    etc.



  • @xaade said:

    And of course there's what I do, which is basically app Hungarian notation, which is basically the same amount of app work done to implement strong typing.

    var dateOfTermination
    

    Is that a native JavaScript Date? An angular moment? A string formatted date that was returned by a JSON deserializer?

    Naming isn't typing.

    Also, trying to understand the advantages of dynamic languages using trivial examples will only leave you without answers.



  • @Jaime said:

    [code]var dateOfTermination[/code]
    Is that a native JavaScript Date? An angular moment? A string formatted date that was returned by a JSON deserializer?

    Naming isn't typing.

    Going to agree with that. Also going to push a bit further and dare claim that those are not the real questions you should be asking. The real question you should be asking is why you even have to care for what will be either a local or a private-by-closure variable that should not be exposed to the outside world. Global variables have stopped being a thing in serious JavaScript programming and it's all modules nowadays, which allow well-documented public APIs.

    Sure; you may need to document the intended type(s) on internals for your own maintainance, in particular when they cannot be inferred from context. In those cases a simple comment that quickly annotates the type(s) should still suffice.

    @Jaime said:

    Also, trying to understand the advantages of dynamic languages using trivial examples will only leave you without answers.

    This times 100. People are seriously overthinking the whole 'but dynamic languages hide type information' and are tossing the baby out with the bathwater by failing to see the whole thing at scale and during a project's evolution over time.

    If you're disciplined, you can get all the velocity and mutability of a dynamic language with most of the type recognizability and stability of a static language still attached. But you have to be disciplined. And sadly JavaScript has the same stigma as PHP; for every good developer there are 20+ complete and utter hacks out there.

    (In case of PHP it's probably semi-justified though, because holy crap is that [...] 'thing' ever a clusterfuck.)



  • @powerlord said:

    In JavaScript, what does 9 + 8 + "7" equal? Personally, I don't know without testing. From the look of it, I'd think "177", but JS may decide that "7" is a number and make that 24 instead... or decide that all 3 are strings and have it be "987". Incidentally, after testing, "177" is the answer according to JSBin.

    C:\Users>node
    > 9 + 8 + "7"
    '177'
    > 9 + (8 + "7")
    '987'
    > (9 + 8) + "7"
    '177'
    

    I tried it backwards as well for Ss&Gs:

    > "7" + 8 + 9
    '789'
    > "7" + (8 + 9)
    '717'
    > ("7" + 8) + 9
    '789'
    

    So what can we learn from this? I dunno, (a + b) + c always equals a + b + c, at least for numbers and strings?


  • Discourse touched me in a no-no place

    Ha! When I hit the show previous post button to see what post of mine you were necroing, I noticed that the quote feature fixes one of @blakeyrat's signature complaints: It displays the list item numbers as I typed them.


Log in to reply