6 ms·
Here are my thoughts after quickly glancing over the „features“: 1. No formatting rules and verbose „end“ I thought that by now it was universally accepted th
by Profpatsch 12y ago
Here are my thoughts after quickly glancing over the „features“:
1. No formatting rules and verbose „end“
I thought that by now it was universally accepted that having clear rules is a good idea, see Python and golang)
2. OO with inheritance
3. multiple at that
4. Dynamic classes/objects
5. Methods inside the classes
All of these make reasoning about effects very hard/impossible; Interfaces in golang, Multimethods in Clojure, Typeclasses in Haskell, CLOS in CL all provide a better solution to that.
6. Imperative
7. No functional elements (no functions, only methods)
Both mean inherently stateful, which in turn complicates reasoning
8. redef & super
It’s dangerous to have behaviour of single methods spread all over your codebase.
9. nullable
Looks like an interesting idea to eliminate the class of NPE runtime errors, yet it’s a special language (and syntax!) construct. It therefore does not arise out of the type system, but is explicitely built into the type system, so it doesn’t scale. See Haskell’s Maybe type on how to eleminate NPE’s with a small, trivial type that is no more special than any other.
Take it or leave it, these are the things I learned in my study of programming languages. I might be wrong, I might be right, but these are the things that came up as bad design most often in different languages. /me out
- ajuc 12y ago> I thought that by now it was universally accepted that having clear rules is a good idea, see Python and golang) It is far from being generaly accepted, see Clojure, Scala, Rust, Ruby, ... I'd say more new languages don't follow this than do. And despite general love for Python its most controversial feature is exactly this.
- kibwen 12y agoRust has had formatting rules in the vein of PEP 8 for years now, and I'm hoping that an automatic rustfmt will emerge sometime between tomorrow's alpha release and the stable release a few months from now.
- steveklabnik 12y agoYes, we absolutely want a rustfmt. There's just been higher-priority work to do, and some conventions are still settling out. Gotta know what to format to before you can build a formatter!
- mhd 12y agoAnd the introduction of mandatory fixed formatting for go (in the name of making semicolons optional) wasn't without some opponents either, if I remember correctly, even in that rather obedient fandom.
- _pmf_ 12y ago> It is far from being generaly accepted, see Clojure, Scala, Rust, Ruby, ... I'd say more new languages don't follow this than do. And despite general love for Python its most controversial feature is exactly this. Maybe, but the question is whether they are better off or worse off for it.
- ajuc 12y agoI'm happy with either python-like, lisp-like or c-like syntax, just ban tabs if you use python syntax please.
- kmicklas 12y agoRegardless of the relative merits of tabs vs spaces, tabs make the most sense _specifically in a Python-like language_.
- ajuc 12y agoI don't care about tabs vs spaces, I just don't want to have the "inconsistent identation" problem, and spaces are more fundamental (you can convert arbitrary tabs to spaces, you can't convert arbitrary spaces to tabs). Also you cannot forbid spaces in code, but you can easily forbid tabs.
- kbenson 12y agoNo, actually the question was whether it's universally accepted as a good idea. Obviously it isn't (universally accepted). No need to turn this into a discussion of the merits, that's been done here many, many times before.
- Profpatsch 12y agolel, of course everyone is going to discuss about the smallest critique I stated. Bikeshedding at its best.
- 12y ago
- steveklabnik 12y agoRuby effectively has a standard format, the only significant diverging style is Seattle Style. It's true that there might be some edge cases, but the vast, vast majority of Ruby code looks the same.
- vorg 12y agoRuby has different styles named after cities, does it? A standard (Tokyo ?) style and a Seattle style? Perhaps we should add the London style, named after Groovy because Groovy's essentially a carbon clone of Ruby except for syntax.
- steveklabnik 12y agoJust Seattle. Members of Seattle.rb do a lot of Ruby infrastructure work, and were around before Ruby really blew up in the states.
- baldfat 12y agoAfter moving from Python and its "clear rules" of having one and only one obvious way of doing things to programming in R. I like R and the flexibility of have many different ways of doing anything. What you lose you gain with quick evolving libraries and work flows. R is light years past where it was just five years ago and Python is still stuck at trying to go from 2.7 to 3.4. R has gone from R 1983 to a fast adapting language due to the flexibility of how you can do something.
- kyllo 12y agoClearly an attempt at a better, but still-not-functional Java.
- MadcapJake 12y agoUmm this is definitely not an attempt at a better but still-not functional Java. This is an attempt at a better Ruby. Not sure of how much they've really differentiated themselves (performance-wise or feature-wise).
- kyllo 12y agoStatic typing does not say "a better Ruby" to me, Ruby is extremely dynamic.
- klibertp 12y ago> I might be wrong, I might be right, but these are the things that came up as bad design most often in different languages. Yes, you are wrong. For every feature you listed and condemned as "bad design" there are examples of languages which implemented this feature in a way that actually makes sense. What I learned from my study of some 40 PLs to date (I actually started counting and documenting this not long ago, which is why I know the exact number) is that there is no such thing as "bad feature" or "feature that results in bad design". No, even straight "goto" is not such a feature. You should either list the features of this language and stop at that or describe the design of the language as whole; saying that a language "has multiple inheritance and therefore is [insert anything here]" is simply unfair.
- Profpatsch 12y ago> is that there is no such thing as "bad feature" or "feature that results in bad design". No, even straight "goto" is not such a feature. Yet, there are features that lead (with a high probability) to bad program code (see goto) Of course it’s always basically the same once a language is turing-complete, so we have to rate languages by how they do certain things. There is the widely-known term of “code smell” or even “antipattern“, I’m pretty certain such a thing exists for language design, too. I did list those features I found lead to “design smell”. By the way, comparing penises by writing out numbers w/o any reference is silly at most.
- klibertp 12y ago> Yet, there are features that lead (with a high probability) to bad program code (see goto) No, I disagree. It's feature usage - or rather misusing it - that leads to "bad code". And that's even before we start talking about what is a "good" or "bad" code, which is OK to discuss on a high-level, but invariably leads to flame wars when it comes to details. > I’m pretty certain such a thing exists for language design, too. What I'm saying is that I didn't see this in action, ie. I found no obvious correlation between any single feature and good or bad language design, across all the languages I learned/investigated (EDIT: where the sample size is 40, also see below). Also, saying that a particular language design is "good" or "bad" is utterly meaningless: the only way of judging PL designs is on how well they suit to some purpose. Take a look at J or Forth - these are beautiful designs, yet you probably wouldn't want to use them to code a basic CRUD app. > comparing penises by writing out numbers w/o any reference is silly at most. My VPS hosting is dead for some reason, but you can see - incomplete, work in progress - list of those languages here: https://klibert.pl/articles/programming_langs.html https://klibert.pl/articles/programming_langs.html (when it comes back EDIT: should be working now). Also, thanks for assuming so much about my mentality from a simple comment; in reality I'm just happy and excited about my new side project, which happens to be about documenting my experience with various languages and their usefulness in polyglot setting.
- Gurkenmaster 12y ago>5. Methods inside the classes Isn't that the point of methods? Or do you mean there is no way to define functions outside of classes? Yeah that's terrible because redef will encourage you to add them to the class of the first parameter.
- Profpatsch 12y agoDon’t you just love some good ol’ Nitpicking …
- xymus 12y agoI'm a developer on the Nit project, I would like to clarify a few points. Classes and types are definitely static in Nit. Class refinement is applied at compilation and any ambiguity is reported at that time. After using this language for a few years, I'm now convinced that class refinement is an improvement to manage preoccupations in projects of any size. It adds an additional layer to the classic object oriented languages. Nit uses classes to encapsulated data only, and modules to separate preoccupations. It saves us from using services classes and instead we can organize our methods in the real receiver of each behavior. Let's take the example of a game. In module `game_logic`, we define the `Game` class with all the required methods and attributes for the full logic. In another module `graphics`, we reopen `Game` to add the `draw` method and the attributes to store the images. We end up with two modules, one that is simple to read and easy to test, and the other with only graphical preoccupations. We can even use class refinement to apply optimization without complicating the base game logic. See the Hunted Dino project for an example of such a structure: https://github.com/privat/nit/tree/master/examples/mnit_dino/src/ https://github.com/privat/nit/tree/master/examples/mnit_dino...
- zzzcpan 12y ago> Interfaces in golang ... provide a better solution to that Hm. What exactly are we talking about here? What problems inheritance and interfaces attempt to solve? I mostly see abuse and overuse of interfaces in golang. It takes way too much time to understand what's going once you have an interface somewhere. The code starts to feel awfully OOish. You start guessing and assuming things, because you get that virtual thingy and finding what's behind this thingy and where is too much effort, you also have to get out of context. OO programmers have IDEs to help with that, but golang is anti-IDE. As a bonus you get that evil OOish style of manipulating internal state from a whole bunch of different methods that call other methods that change state. I guess they like to follow DRY dogma or whatever. Anyway, I don't see how interfaces are better than OO.
- bunderbunder 12y agoIn my experience, implementation inheritance always makes the problems you complain about worse, not better. With implementation inheritance you've got to go and trace a class's entire inheritance hierarchy all the way back to the root if you want to reason about a method's behavior. With interface inheritance the number of implementations you need to look at is always 1. More generally, interfaces give you a way to provide an absolute minimum in semantic guarantees down toward the root of your inheritance hierarchy. This is critical if you want to follow the Liskov substitution principle. And you should always want to follow LSP.
- zzzcpan 12y ago> With interface inheritance the number of implementations you need to look at is always 1. Well, I haven't seen real need for neither of them. Both seem to only make things worse, not better.
- Profpatsch 12y agoExactly. It’s what I commented about super after 8. You spread your (probably stateful, imperative) logic over several files and classes.
- 12y ago
- zak_mc_kracken 12y ago> Looks like an interesting idea to eliminate the class of NPE runtime errors, yet it’s a special language (and syntax!) construct. It therefore does not arise out of the type system, but is explicitely built into the type system, so it doesn’t scale. [Citation needed] Groovy, Ceylon and Kotlin prove that this approach has a lot of merits. > See Haskell’s Maybe type on how to eleminate NPE’s with a small, trivial type that is no more special than any other. Your claim that `Maybe` solves this better is dubious. Yes, it's nice to have this support emerging naturally from the type system but the downside is that you are now wrapping all your nullable values in monads, and if these values are already monads, you enter monad transformer hell (and it spreads to all the function signatures in your entire code base). Of course, there's also the fact that because all these values are now monads, you can only interact with them through layers of flatMaps, which generate a lot of nested and then unnested values along the way. It's quite inefficient. The approach used by Nit and the other three languages I gave above is much more lightweight and, in my opinion, a much more reasonable compromise.
- dragonwriter 12y ago> Of course, there's also the fact that because all these values are now monads, you can only interact with them through layers of flatMaps I can easily (and without using any monad specific operations, bind/"flatMap" or otherwise) write a function that interacts with values wrapped in a Maybe monad. isJust :: Maybe a -> Bool isJust (Just _) = True isJust (Nothing) = False Of course, I can use monadic operations with any type that is a member of the Monad typeclass, but that doesn't preclude having other alternatives.
- dllthomas 12y ago"if these values are already monads, you enter monad transformer hell (and it spreads to all the function signatures in your entire code base)" In addition to dragonwriter's objection, this is basically wrong. You can deal with wrapped maybes without touching monad transformers. Further, MaybeT is quite convenient when you have a lot of operatons that may fail, and you want to give up on the chain if they do. It doesn't spread arbitrarily far, though - at any point you can runMaybeT to turn (MaybeT m a) into (m (Maybe a)), for any Monad m. In general, monad transformers don't propagate crazy far unless they need data that's only available crazy far away.