15 ms·
What amuses me in all "static typing versus..." discussions, is that it usually it is the comparison between two camps: Camp A: Languages with mediocre static
by flavio81 9y ago
What amuses me in all "static typing versus..." discussions, is that it usually it is the comparison between two camps:
Camp A: Languages with mediocre static typing facilities, for example:
-- C (weakly typed)
-- C++ (weakly typed in parts, plus over-complicated
type features)
-- TypeScript (the runtime is weakly typed,
because it's Javascript all the way down)
Camp B: Languages with mediocre dynamic typing facilities, for example:
-- Javascript (weakly typed)
-- PHP 4/5 (weakly typed)
-- Python and Ruby (no powerful macro system to
help you keep complexity well under control
or take fulll advantage of dynamicism)
Both camps are not the best examples of static or dynamic typing. A good comparison would be between:
Camp C: Languages with very good static typing facilities, for example:
-- Haskell
-- ML
-- F#
Camp D: Languages with very good dynamic typing facilities, for example:
-- Common Lisp
-- Clojure
-- Scheme/Racket
-- Julia
-- Smalltalk
I think that as long as you stay in camp (A) or (B), you'll not be entirely satisfied, and you will get criticism from the other camp.
- fulafel 9y agoWhat makes you put Python and JS in the same basket here? Python is widely raised as a language that has a good dynamic typing system with strong types and good type error handling - arguably better than Lisps (nil punning). JS is infamous for the opposite. Macros are quite orthogonal to this.
- flavio81 9y ago>What makes you put Python and JS in the same basket here? I'm very well versed in Python (i've delivered two financial software systems done in Python, written entirely by yours truly). However its features and facilities pale in comparison to the languages i listed in camp "D".
- nnq 9y ago> Macros are quite orthogonal to this. You ain't gonna to find any sane way to combine macros with a powerful type system in a way the doesn't make a 140+ IQ a requirement for any programmer touching the code using these features in a real world project... Problem with programming language design is that the ideal/Nirvana solutions lie at the edge, or beyond, the limits of human intellect. If you want something that can be learnt and understood with reasonable effort (like in not making "5+ years experience" a requirement for even basic productivity on an advanced codebase), you're going to have to compromise heaviliy! The most obvious ways to compromise are throwing away unlimited abstraction freedom (aka "macros"), or type systems. Sorry to break it to ya, but we're merely humans, and not that smart...
- pkd 9y agoThere is a programming language property called Restrictability - it means that you only need to know a subset of the features the language provides to become productive. The best languages have high restrictability without compromising on the high level features like powerful macros. The point of having macros is that they allow you to solve problems that cannot be solved elegantly in any other way. But 95% of programmers don't need to solve such problems and can do very well without using macros.
- alphaalpha101 9y agoBut then you don't have real macros. Real macros, as in Lisp macros, are good because they aren't experts-only. Macros are used by all Lisp programmers, all the time, and they're just another tool in the basket.
- nnq 9y ago> Restrictability - it means that you only need to know a subset of the features the language provides to become productive Thanks, but.... NO THANKS! It's basically what makes languages like Scala or C++ horrible - a false sense of "you only need to know this subset of the language" and then you see that in real life: (1) nobody agrees on what that subset is and (2) you are going to have to hack your way through the most advanced frameworks and libraries (written by folk way smarter than you) and you are going to need to do it under unreasonable time pressure! If a feature exists in the language you will be forced to understand it and become proficient at using it, whether you like it or not. Otherwise you're a "play pen programmer", only comfortable in his little patch of expertise. I'm personally an "Expert Generalist" and like to be confident I can hack my way through anything this shitty life throws at me ;) This is kind of why I'm starting to love forcefully minimalistic, abstraction-wise-rigid, and intentionally "retarded" languages like Go nowadays :) (But yeah, when dynamic is the way to go, I'd prefer a Lisp with macros any time - one extreme or another, never the middle way, I'm not smart enough for it.)
- kazinator 9y ago> it means that you only need to know a subset of the features the language provides to become productive. That only works when you work by yourself (or in a small team to whom you can dictate the language subset), and without any third party code. > But 95% of programmers don't need to solve such problems and can do very well without using macros. Languages that have great macro systems use them to bootstrap themselves. So when you use the standard, documented features, you're using macros. E.g. if you're writing in Lisp and your file begins with (defun ..., you've just used a macro.
- bbatha 9y ago> Ruby Ruby has some of the best meta-programming facilities out there. Yes you can't manipulate syntax in the same way as lisp, but the fact that all methods are message passing and first class blocks make tons of very powerful meta programming possible. Basic features that look otherwise first class are based on Ruby's meta programming facilities like `attr_reader` and friends. Funnily enough, the meta programming facilities of Ruby are precisely what turns a lot of people off. The wtfs per minute of using something like ActiveRecord is super high for people with only passing familiarity because there's so much that that's defined through Ruby's meta programming facilities.
- jaggederest 9y agoI say this as someone that has used and loved Ruby for more than ten years now: Smalltalk has worlds better dynamic and metaprogramming. That said, ruby does have a lot of power, but it's not of the same order as self/smalltalk etc.
- flavio81 9y ago>Ruby has some of the best meta-programming facilities out there. Ruby has meta-programming facilities, but they pale compared to the easiness of doing meta-programming in Common Lisp. In Ruby, meta-programming is an advanced topic (see for example the implementation of the RoR ActiveRecord). In Lisp, meta-programming is your everyday bread&butter, and one of the first things a beginner learns. Because it isn't too different from regular programming!! [The same comment applies, mostly, also to Clojure, Racket, Scheme, and the other Lisps]
- Tade0 9y agoPerhaps it's because the languages you mentioned barely register in statistics(aside from Clojure maybe). Maybe it's simply hard to have both a good type system and a friendly learning curve?
- bad_user 9y agoThe other possibility is that the industry suffers from anti-intellectualism, so we keep reinventing the same 2 languages.
- Tade0 9y agoDo you believe that this is plausible?
- flavio81 9y agoI think this has happened for a long time. First (70s), features from Algol-68, like structured programming or better flexibility for data types, were ported to other languages. Then (80s-present), the features from Smalltalk and Lisp started slowly to be ported to other languages, many times in an incomplete or unelegant way. We're still doing this, for example the last production spec of the Java language finally incorporated a mechanism to pass functions as input parameter on a method. And the next version of Java (9) will attempt to have some interactivity, with a kind of REPL. This, coupled with the powerful facilities of good Java IDEs, will give Java developers of 2017 the level of Interactivity and easiness of development that Smalltalk and Lisp users have enjoyed since the late 70s. Sad but true. Julia -an interesting language, by the way- borrows multiple dispatch from the Common Lisp Object System (CLOS), among other features. CLOS itself was a further evolution of the OOP brought to the table by Smalltalk, invented by a true genius: Alan Kay. Rust is basically a "fixed C++", that is, a more usable, less annoying C++. So it's difficult to say there are truly new things in programming language. But it's not everything limited to Smalltalk and Lisp -- Prolog, ML (and OCaml, F# and Haskell) do bring new concepts to the table, and are worth checking out.
- 9y ago
- Inityx 9y agoWhere's Rust in here?
- alkonaut 9y agoCategory C
- andrewla 9y agoIt's Camp D that I'm least familiar with here; outside of academic projects in lisp/scheme I've never used them for anything serious. What exactly does it mean to have "good dynamic typing facilities"?
- pkd 9y agoIf you Google, you can find tons of good stuff written in Lisps. Julia is an up-and coming language - but it is highly regarded by the data science community. > What exactly does it mean to have "good dynamic typing facilities"? The ability to change the structure of your program at runtime will be at the top of the list for me. You can't do that with Ruby/Python.
- flavio81 9y ago>What exactly does it mean to have "good dynamic typing facilities"? Picking Common Lisp as an example: (NOTE: Some of the features are also present in good statically typed languages as well, so what I advocate is to use good, well-featured languages, not really static vs dynamic.) (NOTE 2: I'm sorry for being such a fanboy, but that thing is addictive like a hard drug...) 0. Code is a first class citizen, and it can be handled just as well as any other type of data. See "macros" below. 1. The system is truly dynamic: Functions can be redefined while the code is running. Objects can change class to a newer version (if you want to), while the code is running. 2. The runtime is very strong with regards to types. It will not allow any type mismatch at all. 3. The error handling system is exemplary: Not only designed to "catch" errors, but also to apply a potential correction and try running the function again. This is known as "condition and restarts", and sadly is not present in many programming languages. 4. The object oriented system (CLOS) allows multiple dispatch. This sometimes allows producing very short, easy to understand code, without having to resort to workarounds. The circle-ellipse problem is solved really easily here. (Note: You can argue that CLOS is in truth a statically typed system, and this is partly true -- the method's class(es) need to be specified statically, but the rest of arguments can be dynamic.) 5. The macro system reduces boilerplate code to exactly zero. And also allows you to reduce the length of your code, or have very explicit (clear to read) code at the high-level. This brings down the level of complexity of your code, and thus makes it easier to manage. It also reduces the need for conventional refactoring, since macros can do much more powerful, automatic, transformations to the existing code. 6. The type system is extensive -- i am not forced to convert 10/3 to 3.333333, because 10/3 can stay as 10/3 (fractional data type). A function that in some cases should return a complex number, will then return the complex number, if that should be the answer, rather than causing an error or (worse) truncating the result to a real. Arbitrarly length numbers are supported, so numbers usually do not overflow or get truncated. (Factorial of 100) / (factorial of 99) gives me the correct result (100), instead of overflowing or losing precision (and thus giving a wrong result). So you feel safe, because the system will assign your data the data type that suits it the best, and afterwards will not try to attempt any further conversion. 7. The type system is very flexible. For example, i can (optionally) specify that a function's input type shall be an integer between 1 and 10, and the runtime will enforce this restriction. 8. There is an extensive, solid namespace system, so functions and classes are located precisely and names don't conflict with other packages. Symbols can be exported explicitely. This makes managing big codebases much easier, because the frontier between local (private) code versus "code that gets used outside", can be made explicit and enforced. 9. Namespaces for functions and variables (and keywords, and classes) are separate, so they don't clash. Naming things is thus easier; this makes programming a bit more comfortable and code easier to read. 10. Documentation is built into the system - function and class documentation is part of the language standard. 11. Development is interactive. The runtime and compiler is a "living" thing in constant interaction with the user. This allows, for example, for the compiler to immediately tell you where the definition of function "x" is, or which code is using such function. Errors are very explicit and descriptive. Functions are compiled immediately after definition, and it can also be dissasembled (to machine language) with just a commmand. 12. Closures are available. And functions are first-class citizens. 13. Recursion can be used without too many worries -- most implementations allow tail call optimizations. 14. The language can be extended easily; the reader can also be extended if necessary, so new syntaxes can be introduced if you like. Then, they need to be explicitely enabled, of course. 15. There is a clear distinction between "read time", "compile time" and "run time", and you can write code that executes on any of those three times, as you need. 16. Function signatures can be expressed in many ways, including named parameters (which Python also has and IMO is a great way to avoid bugs regarding to wrong parameters / wrong passing order.)
- woolvalley 9y agoSo where does Java & C# fit in those categories?
- richdougherty 9y agoProbably Camp A. They have some static typing, but it's pretty basic. Then again, according to the article posted, they may be in the "sweet spot" for many purposes.
- richdougherty 9y agoLanguages like TypeScript and Racket are also interesting because they let you shift camps partway through the project - you can start of untyped and then add typing annotations. https://en.wikipedia.org/wiki/Gradual_typing https://en.wikipedia.org/wiki/Gradual_typing
- arunix 9y agoHow are the dynamic typing facilities in Smalltalk better than those in Ruby?