8 ms·
What can I do with dynamic typing that I can not do with static typing?
- PommeDeTerre 14y agoYou can more easily make type-related coding mistakes that won't be caught until after your app is in the customers' hands.
- antidoh 14y agoAnd the flip side of that, you can code much more according to interface and be less concerned with the specific type of bits in a variable.
- DannoHung 14y agoI'd like you to back that assertion. Why couldn't your types mirror your interface?
- antidoh 14y agoprintf, you have to know ahead of time whether you're going to be printing a string or a number. In python you just print
- DannoHung 14y agoprintf is not statically typed. That's the problem. What's the type of printf? it's int printf(const char *,...) The "..." part means that the function has to figure out what the types of all the arguments are. printf accomplishes this by, at runtime, parsing the string format and deciding what types to use. Contrast with a string representation function from a language like Haskell: show::(Show a) => a -> String No matter what argument is provided to the function show, as long as it observes the type constraint (Show a), a sensible result will be returned. Since it is known at compile time whether the argument observes the class constraint, there's never a surprise that value is printed incorrectly.
- 16s 14y agoThis is true in the absence of testing. There are tools (pylint, etc.) that will catch many type-related errors.
- eckyptang 14y agoIt is also true when testing is included and pylint are used, which is the issue. I can write a 500 line C# program and it works reliably first time with no crashes, type inference errors or framework exceptions thrown. The only errors will be algorithmic or functional (i.e. based on requirements). The same is not true with python. I have the same experience with both. Go figure.
- ajanuary 14y agoYour tests should be picking the majority of your algorithmic and functional errors, so I'd have to assume you're talking about the state of the code before thorough testing. What's it like after that testing? How's the long term maintainability? I'm much more interested in possible problems - and it could go either way - in the long term than before I've finished writing it.
- eckyptang 14y agoThey do. I tend not to write oodles of test cases up front in favour of simple scenario based tests applied later on. I add pre/post/invariant-condition checks in the code as I write it. It is tested incrementally by hand. The condition checks prevent the what if's and tell you why something broke. The scenario tests ensure that it does what is asked of it. I rarely get bugs raised against my code (7 this year out of about 112,000 lines of c# written). Not bad!
- 16s 14y agoIt's been my experience that python (or any other similar language) is less prone to type errors when testing and pylint are used. I still prefer C++ and a strong type system when I do more critical work, but I can get by with the fast, more reckless languages too. There's a place for both.
- draegtun 14y agoThis is why use strict in Perl is such a godsend because it catches all variable name typos at compile time. Update: Just noticed you said type and not typo related! Still use strict does catch a lot of silly errors that unfortunately do slip into code with other dynamic languages.
- crntaylor 14y agoI think he meant 'typo' rather than 'type' - it was probably a type.
- deleted 14y ago[deleted]
- PommeDeTerre 14y agoNo, I meant "type", exactly as I wrote it. I was not referring to situations where the programmer accidentally types a character or two incorrectly, without realizing it. I'm talking about cases where the programmer intentionally writes code in a certain way, but does not realize it violates a type constraint of some sort. Maybe he passes a string to a function that expects a numeric value. Or maybe he renames a method, but misses one invocation. You get the idea. Please don't assume that what was written was wrong, especially when it wasn't.
- crntaylor 14y agoIt was a joke. Notice how I deliberately mis-spelt 'typo' in the second sentence.
- tripzilch 14y agoI believe you, because that intuitively makes sense, but can anyone give me a typical real-world example where this could easily happen? So an application, say a web application in Python using some framework, what kind of type-related coding mistakes could you make? And which ones would be subtle enough to only be caught after it's in the customer's hands? (assuming a reasonable minimum of testing before that) I'm asking not out of disbelief, but just because I'm having a real hard time coming up with an example that makes me "yeah I'd fall for that and only realize until after I delivered". Is it possible that maybe, just general good coding style in Python makes it so that either you don't even consider sending a `str` to a function that expects a `float`, or that if you do (something like that) it fails almost immediately with a run-time Exception, way before you think of delivering? For most of my Python programs, once they're done, if you'd analyze them, the types sent over all code paths probably would be static :) I'd think it pretty strange if a program would suddenly call functions with different parameter types, depending on user-input, unless you actively decided that it should do so by design (like something that handles arbitrary JSON-like structures), in which case you probably intend to restrict the amount of types it will be intended to handle. So in that sense, you end up with what is mostly a statically typed program in the end, even if written in a dynamic language, no? One thing I do agree that if your program is written dynamically typed and intends to keep on being very dynamic about its typing even after it's done during run-time then, yes, it's probably almost impossible to make sure it does not crash or throw exceptions, given arbitrary user input. But in that case, often this is expected, and not the kind of program you'd consider an end-user application, but rather a sort of tool script thing that can indeed crash on unexpected input. Which is also useful :) So, and correct me if I'm wrong, but I'd conclude that the difference is that with dynamic typing, there's less red tape during development. But a well written program intended for end users probably ends up with mostly static types de facto because otherwise it'd be fairly unpredictable. However, if you'd have used a statically typed language, you would not have to assume "well written" because the static typing brings guarantees with it.
- KMag 14y agoSome advantages of static typing show up in programming in the small. Errors in forgetting to check for null/nil/None are a common class of errors that are caught by many static type systems. Switch/match statements that leave out possibilities without providing a default (especially if a new value is added to an enum) are also common errors that are caught by some type checkers. One hidden (and seldom discussed) feature of static type systems is that in multi-team projects, they can enforce and document abstraction layers between teams. I've even seen static type systems act as impartial arbiters when an argument arises as to if a given change broke one side of an abstraction barrier, or if the change merely exposed a latent silent bug on the other side of the abstraction barrier.
- lmm 14y agoYou can use a function with different types in a way the original programmer didn't think about. Obviously this has good and bad aspects. My "whoa" moment with python typing came when I implemented euclid's algorithm (for the gcd of two numbers). Shortly later, I wrote a polynomial class, and then I was able to use my original function on polynomials without changing a single character In some statically typed languages that would be possible if I'd thought to write my original function generically. But at the time I hadn't even thought about calling it with anything other than integers.
- Robin_Message 14y agoPlaying statically-typed advocate for a moment: in Haskell, you wouldn't have had to put a type down for the function, and the compiler would have inferred the type gcd :: Num a => a -> a -> a which means it is a function that takes 2 a's and returns an a, with the restriction that a is of typeclass[1] Num, that is numbers. So, very much possible and assumed without thinking about it too much. [1] A typeclass is a like an interface.
- crntaylor 14y agoSmall correction; with the most common implementation of Euclid's algorithm the compiler would infer gcd :: Integral a => a -> a -> a since writing Euclid's algorithm requires using `mod` or `rem`, both of which only work for integral types (NB. there are many integral types beside ints, for example polynomials, formal power series and gaussian integers). The Integral class captures the mathematical idea of a Euclidean domain, which can loosely be thought of as "number systems for which the Euclidean algorithm works".
- qznc 14y agoWell, pray that the library function is general enough. Unfortunately, this is not the case for your gcd type, as gcd can be generalized to arbitrary commutative rings. Nevertheless, writing generic code is of course possible with static types.
- 14y ago
- ajanuary 14y agoThe the core of it for me is you can almost always do x under a particular static type system. But you can almost always do the same thing under /any/ dynamic type system.
- gambler 14y agoYou can generate fieleds of ORM objects based on the values returned by a query. If you're writing a game, you can represent in-game objects directly with language objects and add more properties and methods when they're modified. In short, you can cut down on abstraction layers when working with behaviors that are inherently runtime.
- ajanuary 14y agoIt's perfectly possible to have a dynamic type system with closed objects (can't add properties). Then again it's not really possible to have a static type system with open objects (at least, I can't think how you would).
- kd0amg 14y agoThere exist type systems that can handle "strong" (i.e. type-changing) updates, but the ones I know of will only permit it for unique (linear/affine) references. You might be able to take advantage of the guarantee that properties are not being removed, so the update just turns the object into a subtype of what it once was. Then other pieces of code with reference to that object can continue on type-safely, but they won't be able to use those new properties without somehow being informed about them (statically).
- tedunangst 14y agoJust use a dictionary or hashtable.
- icebraining 14y agoBut then, what have you really gained? A more cumbersome syntax? Because that's still unverifiable by the compiler.
- tedunangst 14y agoThat's kind of my point.
- 14y ago
- lihaoyi 14y agoThe main thing that I see dynamic languages as having over static languages is metaprogramming. See http://stackoverflow.com/questions/8276387/statically-typed-metaprogramming http://stackoverflow.com/questions/8276387/statically-typed-.... Metaprogramming is prevalent in python/ruby, regardless of how confusing it is, because it is super useful. Being able to dynamically construct types and classes (e.g. via decorators in python) allows you to do tons of stuff that is otherwise really hard for library writers, even though you shouldn't be using metaprogramming all over the place day-to-day. Rails, SQLAlchemy and a ton of other libraries/frameworks use metaprogramming all over the place. Static languages lack this ability, but because it's so useful, they end up re-implementing the same thing anyway but using reflection/bytecode-manipulation/extra-compile-hooks/code-generation/etc.. like in Spring/AspectJ/Play/ASP.NET! Although the end result is kinda the same, I'd argue metaprogramming via generating java source code is way harder than metaprogramming in python, where creating a new class and setting its methods or descriptors is as easy as creating/fleshing out any other object. Given how powerful/useful metaprogramming is, I think that that's the biggest gain of dynamic over static languages.
- darkstalker 14y agoThat's possible because the language runs on a VM that contains metadata about your data structures, not because of the dynamic typing. If classes are implemented as a hash table of it's fields, then it's easy to add/remove members at runtime.
- colanderman 14y agoStatic languages lack this ability cough MetaOCaml [1] cough cough first-class modules in OCaml [2] cough explanation -- MetaOCaml provides what is essentially a typed eval for Objective Caml. OCaml's first-class modules provide the ability to construct types, classes, and modules at run time. In other words, statically typed languages do have this ability. [1] http://www.metaocaml.org/ http://www.metaocaml.org/ [2] http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual021.html#toc81 http://caml.inria.fr/pub/docs/manual-ocaml-4.00/manual021.ht...
- icebraining 14y ago
- minhajuddin 14y agoMeta programming is much much easier in dynamically typed languages like ruby. It completely eliminates the use of interfaces, because you can call any method on any object. If you want to do it defensively, just check if the object has the method you want on it before calling it. I think statically typed languages have a lot of ceremony around doing something, whereas dynamically typed languages just get out of your way.
- silverlake 14y agoIn mainstream statically-typed languages, you can't build a generalized curry function. (define curry (f . cargs) (lambda moreargs (apply f (append cargs moreargs))))
- tedunangst 14y agoC++ isn't mainstream?
- darkstalker 14y agoBoth can do the same (they are turing complete), but some things are harder to do in statically typed languages because of the underlying implementation, like reflection or eval(). Static typing is safer (more compile-time checks) but more verbose. Type errors are found by the compiler before the program runs. With dynamic typing you write less, but requires better understanding of the underlying types so you don't get runtime errors. Type errors propagate through the program until it generates a runtime exception or wrong results.
- papsosouid 14y ago>Static typing is safer (more compile-time checks) but more verbose No, explicit typing is more verbose. Static typing does not mean java. Many statically typed languages have type inference, and have for a long time. They are no more verbose than dynamically typed languages.
- crntaylor 14y agoPython (dynamically typed): def square(x): return x * x Haskell (statically typed): square x = x * x
- darkstalker 14y agoI'm not familiar with Haskell.. how is the static typing used in the second example?
- Raphael_Amiard 14y agoHindley-Milner like type systems can deduce the type of vars from how they are used. In the square example, using the "*" operation give the information to the type system that x is a number.
- icebraining 14y agoCan you do f = lambda r, a, b: r(a), r(b) f(lambda x: x, 5, "Test") in Haskell without writing types?
- bryanlarsen 14y agoLots of people don't realize that strong/weak typing is orthogonal to static/dynamic typing. Strong typing systems will throw an error if the wrong type is used. A weakly typed language will attempt to coerce or cast the variable. Python is much more strongly typed than both Javascript and C. Another dimension is the explicitness of your variable languages. This isn't quite orthogonal since static languages have to allow you to specify a type and dynamic languages have to have some way for you to not specify a type but many static languages allow you to infer a type and many dynamic languages allow you to specify types. (You can always use asserts if they don't explicitly allow it). My point is that inferred types always have the potential to provide surprising results. It is unlikely in static languages, but it's possible. If you've defined "square x = x * x" it will allow you to square anything that has the splat operator defined for, even if that would be nonsensical. For that reason inferred static languages generally don't overload the splat operator, so it's a bad example. But I hope you still get my point.
- draegtun 14y agore: strong/weak/dynamic typing, coercion & overloading And the mix can produce interesting results. For eg. in Python: def double(x): return x * 2 print double(2) # => 4 print double("X") # => XX If you were expecting a number to be returned then this isn't good :( The * operator isn't overloaded in Perl so instead we get: sub double { $_[0] * 2 } say double(2); # => 4 say double('X'); # => 0 Perl is more weakly typed than Python so 'X' get coerced to zero with the multiplication operation. So at least a number is returned but I would prefer a warning or error: use warnings; say double('X'); # produces runtime warning use warnings FATAL => 'all'; say double('X'); # produces runtime exception
- qznc 14y agoWhat you can do with your statically typed language obviously depends on the strength of the type system. Haskell for example is quite good, but Java is very limiting. Luckily there is a workaround for Javas static typing limitation: Casts. Every time a Java programmer uses a cast, you can see that static typing has limits.
- ddimitrov 14y agoIn a dynamic languages you can do dynamic dispatch - i.e. dispatching based on the actual runtime type of the arguments of a function, as opposed on the declared or statically inferred type. That among other things obviates the need for the visitor pattern and can also be used as rudimentary form of pattern matching.
- BerislavLopac 14y agoThe crucial moment in my understanding of dynamic languages was when I was learning about the Abstract Factory pattern by implementing it in PHP. After writing different factory classes and all the shenanigans I've realized that all of that can be replaced with a simple $instance = new $classname(param1, param2)