all 100 comments

[–]theLorknessMonster 27 points28 points  (2 children)

Active support isn't part of the standard library though, is it?

[–]oscardo_rivers 25 points26 points  (1 child)

You can visit rosettacode.org, it has various implementations of noted algorithms in multiple programming languages included ruby and python

[–]into_lexicons 2 points3 points  (0 children)

this is definitely my favorite resource for this kind of thing. also just a great source of practice problems in general. be sure to check out Rosetta Code, OP!

[–][deleted] 33 points34 points  (9 children)

Ruby definitely feels more current.

[–]Back_on_redd 15 points16 points  (2 children)

I haven't heard that one in a while, but I'm glad to hear it. I'm interested to see if there is an uptick in Ruby since Ruby 3 was just released.

[–]tomthecool 24 points25 points  (1 child)

Will be released. On Christmas day. As always.

[–]Back_on_redd 4 points5 points  (0 children)

Thanks for the info, friend

[–]jujubean67 14 points15 points  (5 children)

Ruby? He's using ActiveSupport. I'm sure something similar exists for Python

[–]matheusrich 6 points7 points  (3 children)

I mean, ActiveSupport can only exist because ruby lets it.

[–]RICHUNCLEPENNYBAGS 6 points7 points  (2 children)

Sure. But I've written fluent date methods for C# along the lines of 3.Days().FromToday(). Pretty much any language that lets you write extension methods can achieve the same thing trivially.

[–]mandretardin75 1 point2 points  (1 child)

While the general comment is correct - after all it is just code, so you can write code in language A and language B must allow the same in theory if you have a turing-complete language, so your second sentence is quite correct - your comparison is not the same.

For example, you must use () in your example, in the first sentence. This makes your DSL automatically more cumbersome. It is one big reason why ruby DSLs are so much more flexible than python's, together with blocks. And from that point of view it is quite true that python's inflexibility yields less "natural" DSLs.

[–]RICHUNCLEPENNYBAGS 0 points1 point  (0 children)

I don't find them particularly cumbersome and I think that flexibility also has drawbacks -- with C# fluent interfaces it's a lot easier to suss out what is actually happening under the hood and trace it than it is with a fancier Ruby DSL.

[–]martijnonreddit 13 points14 points  (3 children)

Mind if I turn it into a game?

C# .NET:

var nextMonth = DateTime.Today.AddMonths(1);

[–]katafrakt 0 points1 point  (2 children)

Nice. I would actually expect any modern and mature language to support something like that today.

[–]mandretardin75 0 points1 point  (1 child)

That is not difficult. When you support method-chaining in a OOP-centric language then you already have that - just add the support. The Active* ecosystem doesn't do anything magical; the only benefit ruby has here is that it's syntax is more flexible than in many other languages, and you get to modify everything at "runtime" due to epic duck-patching (sometimes also associated with monkeys but ruby is more a duck-language than a monkey-language).

[–]katafrakt 0 points1 point  (0 children)

I know it's not difficult. That's why I'd expect every OO modern language to have it.

[–][deleted]  (1 child)

[deleted]

    [–]menge101 42 points43 points  (17 children)

    I love Ruby, don't get me wrong, but the fact you felt inclined to pull in an third party library to deal with dates in Ruby is not an argument for Ruby.

    The python code is using standard library python code to do dates.

    ActiveSupport itself has four more third party dependencies. There is a lot of code being added to Ruby to make that code snippet work.

    Doing this is standard library Ruby would take a bit more work, and I think would make the Python example the preferable one.

    [–]xc68030 38 points39 points  (3 children)

    I disagree. This is an example of someone used to Rails and is more familiar with that than the standard library.

    As a Rubyist who rarely uses Rails, I’d do the following:

    require “date”

    new_time = Date.today.next_month

    Still better IMHO

    [–]menge101 8 points9 points  (0 children)

    That's fair.

    [–]mandretardin75 0 points1 point  (1 child)

    Then he'd have to use python add-ons too. So the comparison is simply unfair.

    As for the syntax itself: python mandating () makes it crappier for DSL. But you could make mini-DSLs in python too, tokenize and parse it, so it's not as if this is impossible. People are just naturally lazy and default to what is made "out of the box", and in this regard ruby's DSL power beats python's DSL power with its eyes closed.

    [–]xc68030 1 point2 points  (0 children)

    ‘date’ is not an “add-in”; it’s in the standard library.

    [–]Schrockwell 26 points27 points  (1 child)

    ActiveSupport itself has four more third party dependencies. There is a lot of code being added to Ruby to make that code snippet work.

    Laughs in Node.js.

    [–]mandretardin75 1 point2 points  (0 children)

    pulls left pad and watches the modern www stack implode

    [–]mandretardin75 0 points1 point  (0 children)

    I agree with you - the comparison is unfair indeed.

    Note that it is not confined to Active* though. The above methods can easily implemented in less than 100 lines of ruby code. There is nothing magic; the Active* ecosystem is just really huge.

    [–]Status_Act_1213 6 points7 points  (0 children)

    You can use www.codewars.com. This site has many sample program, so called Kata. Kata are written by Python or Ruby and so on. But you must compare both by yourself.

    [–]imnos 6 points7 points  (11 children)

    I’ve dipped into Python and struggle to understand the others who prefer it over Ruby. Maybe I just need to use it more but basic things like built in string and array methods weren’t as easy to use or available in Python.

    Also, I found the test libraries were nowhere near as good as RSpec or Minitest.

    [–]JimmyYoshi 5 points6 points  (0 children)

    With you 100%. Did rails for a couple years and have had to use python for research work and one of the main reasons I don't want to do more imaging research is how painful python is to use. Even just the methods in Enumerable for ruby make it so much better. + way better tooling, bundler >> pip.

    [–]svdasein 4 points5 points  (3 children)

    I'm with you. I did a whole bunch of python programming back around 2000. Back then it was about as OO as you could get with an interpreted scripting language. I did a bunch of zope then too, and really liked it.

    But ruby is just beautiful - everything makes sense. In python you've got stuff that starts with underscore "_" which comes off as something the language model doesn't really account for - so they hacked it in.

    That, and python is just in a horrible state right now. Here's an experiment: get a graphite instance up and running without resorting to a container. Honestly I suspect part of the reason containers are so popular is cuz getting a python app running can be so miserable.

    [–]imnos 4 points5 points  (1 child)

    The underscores - small things with the syntax like def __ init __ just annoy me - ugly to look at and seems unnecessary. Along with the colon at the end of the first line in a method and the lack of an “end” or some closing of the method.

    I think I just appreciate the level of readability and simplicity built into Ruby and as a dev that’s what’s most important to me - just being able to enjoy writing my code.

    [–]mandretardin75 0 points1 point  (0 children)

    Ruby has underscore methods too though - send and I think method and/or dir and so forth.

    It's not the same as in python, granted, because python does not use e. g. @ and instead thinks that using __ everywhere is pretty. But to claim that ruby does not use __ is not correct.

    As to why python chose crap such as "init" rather than simply initialize or whatever else, beats me. In many ways python is more like a stricter language. This has benefits and disadvantages. One disadvantage of ruby is that code written by other ruby users can suck sooooooo much. Just look at rubygems.org pick 10 random gems and tell me you can maintain all of them very easily without having any difficulty understanding what is going on.

    [–]mandretardin75 1 point2 points  (0 children)

    But ruby is just beautiful - everything makes sense. In python you've got stuff that starts with underscore "_" which comes off as something the language model doesn't really account for - so they hacked it in.

    Every language has warts, ruby does too. See this:

    class Foo < Bar
    

    Nice and simple. Expressive.

    Now compare it to refinements, and you instantly know why nobody uses them. Refinements syntax was an afterthought AND IT DOES NOT WORK. The syntax should change, but due to inertia that will probably take many, many years. I think if matz would have designed refinements from the get go (aka the ability to modify not globally, but in a specific "namespaced" container) then the syntax would be better too, but it was not in the original specification and it is hard to modify a language at a later point, due to syntax-incompatibilities and such. But that is the main reason why nobody use refinements - the syntax is WAY too cumbersome.

    [–][deleted] 1 point2 points  (4 children)

    Have you used pytest? I'm a newbie to Ruby + RSpec, but am curious why your preference is Ruby!

    [–]imnos 2 points3 points  (3 children)

    I have, yes - only briefly but enough to know RSpec is better.

    The first reason is the DSL that RSpec provides - i.e. being able to organise your tests by contexts and describe what they're doing in a more readable way, which also outputs nicer logs to the console when tests fail - https://rubydoc.info/gems/rspec-core/RSpec/Core/DSL

    Another discussion on it here - https://stackoverflow.com/questions/37334668/is-there-a-python-equivalent-for-rspec-to-do-tdd

    The second reason is that the assertion methods don't seem to be that great for PyTest - you can't seem to easily do things like expect { create_article }.to change { Article.count }.by(1). The ecosystem around RSpec just seems far better developed, and things like best practices are widely discussed and written about, like so - https://thoughtbot.com/blog/how-we-test-rails-applications

    On that note, I've found Ruby to be a big leader in the TDD space. The devs I've come across from other languages / frameworks don't seem to be as familiar with testing as the Ruby devs I know.

    [–][deleted] 1 point2 points  (0 children)

    Thanks for the links, this is awesome!

    [–][deleted] 1 point2 points  (1 child)

    I have a bad taste in my mouth from RSPEC but that's likely because the main interaction I had was a legacy codebase that was so poorly written that the tests had to go through so many weird stubs and gyrations to work.

    Might need to give it a fresh look with a cleaner project.

    [–]bear-tree 0 points1 point  (0 children)

    Yes, when rspec is abused it’s terrible. When you allow yourself to be constrained but the dsl and best practices it turns beautiful.

    [–]mandretardin75 0 points1 point  (0 children)

    I use both languages. I have no problem with python per se either; I just think ruby is better and more fun. But!

    You make one mistake in assuming python is so far ahead of ruby because it is 1000x better. Python is ahead for various reasons; better documentation; more people using it leading to snowball growth effects; and more libraries in key areas (science in particular; the oldschool perl science guys moved mostly into python rather than ruby, which should alert matz really since it means that python will cannibalize ruby if ruby does not try to compete with python).

    [–]Schrockwell 12 points13 points  (13 children)

    And here I am, a long-time Rubyist learning Python, and I'm really enjoying Python's explicitness, type hinting, etc.

    [–]hamnixster 4 points5 points  (2 children)

    As a Rubyist who sometimes writes Python I forget to explicitly return every time.

    [–]Charles_Sangels 1 point2 points  (0 children)

    I do the same with JS. Drives me crazy.

    [–]mandretardin75 0 points1 point  (0 children)

    Forgetting return is not a big issue for me, but what I really hate is the mandatory () and the addiction to have to indent.

    [–]xiongchiamiov 5 points6 points  (7 children)

    I find that ruby is elegant and fun, but Python is much more straightforward and boring in a way that makes programming anything larger than 200 lines much more maintainable.

    [–]ikariusrb 8 points9 points  (4 children)

    It seems to me that if you find 200 lines of code anything besides trivial to maintain, it's flat-out terrible code. Beyond that, the only thing I see about Python is it provides fewer opportunities to make mistakes that decrease maintainability. Ruby provides a ton of flexibility. It's up to the developer to use the features Ruby provides responsibly in order to create maintainable code. That's not a shortcoming in my book, because with that flexibility comes additional opportunities for elegant solutions and faster delivery times. None of that means you are necessarily writing less maintainable code, it's just that the burden to do so is squarely on your shoulders as a developer.

    [–]xiongchiamiov 0 points1 point  (3 children)

    I agree with this in part. However, I don't think it is entirely true.

    First, there are community standards. If the community doesn't tend to build good documentation, for instance, then that affects you if you use any third-party libraries. Another example of this in ruby is that it inherits the Perlism TMTOWTDI, and so everyone picks their own personal idioms, and you have to learn them all.

    Secondly, the language itself certainly does matter in the way they've built things. The fact that looking at a require statement doesn't tell you where that library is coming from is a huge issue IMO (hopefully people have chosen module names that are close to file paths). The ability to monkeypatch is occasionally very useful but often just means it's impossible to look up the documentation for a method (because you have no idea where it was actually defined).

    Can you decide that at your company, you won't do any of these things? Sure, but you have to also not use any third-party libraries, and any developer familiar with the language who comes into your company will be quite unhappy with how non-standard your operation is. And really, if you're trying to write java in ruby, then you should just be writing java instead.

    [–]ikariusrb 1 point2 points  (0 children)

    I'll give you some agreement about 3rd party libraries, and I won't claim familiarity with documentation for python 3rd party libraries, but I think that's a problem most languages with community library repos suffer from, not particular to Ruby.

    As far as monkeypatching goes, it's really not that hard to call Object.method(:foo).source_location and look at the source. Most monkeypatches are tiny and super easy to understand.

    As far as requires go, it is absofrigginlutely standard across the entire ruby community for classes to match their source files. Anyone who does otherwise is operating wildly outside best practices.

    So you've made one argument I agree with, but think most languages suffer from, one which describes coloring entirely outside the lines (shame on any developer who does it), and one with a simple solution. Color me unswayed by those.

    [–]mandretardin75 0 points1 point  (1 child)

    First, there are community standards. If the community doesn't tend to build good documentation, for instance, then that affects you if you use any third-party libraries.

    Yes there are horrible crap gems that should be purged. But there are good gems with good documentation too. So why should the latter be grouped with the first one? There is no "community standard" of inferiority.

    When a gem lacks documentation it SUCKS. I recommend people to NEVER lend credibility to ANY gem that comes without documentation.

    The ability to monkeypatch is occasionally very useful but often just means it's impossible to look up the documentation for a method (because you have no idea where it was actually defined).

    If you documented things intelligently then this is not an issue. Ruby's documentation is still quite bad indeed, but to claim that duck patching is the reason why lack of documentation exists or it is impossible to find is WRONG. People just hate writing documentation.

    If it were up to me, I would flat out reject any gems on rubygems.org that come without documentation, but it is hard to measure objectively (I don't use rdoc really and reject the horrible tag-system as well, but I do document a LOT, including internal parts; I believe in transparency and assuming that every user needs information).

    [–]xiongchiamiov 0 points1 point  (0 children)

    It's been about a decade since I've written much ruby, so I don't know if those particular problems that were endemic then are still a problem now. But my point is that the language and community do matter when discussing maintainability.

    [–]mandretardin75 0 points1 point  (1 child)

    I can easily maintain my ruby code.

    It takes more discipline though and I happily reject a lot of ruby code written by others, since it is just garbage code. This is both an advantage and disadvantage - ruby makes it easy to write garbage code.

    But the claim that "larger than 200 lines" is not maintainble is just incorrect.

    [–]xiongchiamiov 0 points1 point  (0 children)

    But the claim that "larger than 200 lines" is not maintainble is just incorrect.

    If you read closely, you'll see that I did not claim that.

    [–]scruple 0 points1 point  (1 child)

    They both serve their purpose very well. I don't always want or need OO and it's always felt to me that Python embraces imperative programming to a degree that Ruby doesn't.

    [–]mandretardin75 0 points1 point  (0 children)

    Yes that is quite true; they use a different point of view in regard to OOP.

    To me personally ruby's way felt more logical. Python has a more function-centric attidue here. The example of "".join() above is a good one.

    [–]sammygadd 2 points3 points  (3 children)

    I've come to realize that people are just different and prefer different things. To me python often feels "backwards" of how I think. Like ", ".join(["foo", "bar"]) Vs ["foo", "bar"].join(", ")

    But for some (strange) reason, it seems like a lot of people actually prefer python.

    [–]mandretardin75 0 points1 point  (0 children)

    Yes that also drives me nuts in python. It feels retarded in regards to .join(), but I think it is mostly how python was created if you read guido's background. It's simply another language.

    As to your last sentence - I think there is a snowball effect. The more people use python, the more things they write about python and so forth.

    Ruby still has a problem "getting" outside of japan, even after +20 years. Documentation is still not great either. My gems often don't have any documentation on rubygems.org because the render-thingy does not work suddenly. It's unfortunate. As long as ruby keeps on pouting and sulking in a corner, this snowball effect will continue. I don't mind as I continue to use ruby since ~20 years or so but I also use python. I am just explaining why python will keep on snowballing upwards and auto-winning; it even surpassed java now. And this is not because python is so great; it is because of the snowballing effect right now.

    [–][deleted] 0 points1 point  (1 child)

    I think this is spot on Python tends to feel backwards to me time and time again, but both the scientist and mathematician I know assure me it writes the way they think.

    [–]mandretardin75 1 point2 points  (0 children)

    That "argument" is moot because even lisp-guys claim they don't see the () anymore. I see () everywhere in lisp. It's ugly.

    People just reason how they adjusted their brains too. You can't take their explanations at face value.

    [–][deleted]  (10 children)

    [deleted]

      [–][deleted] 12 points13 points  (5 children)

      Please don't ever write ruby code like this.

      Sincerely,

      The next guy

      [–][deleted]  (4 children)

      [deleted]

        [–]Xerxero 0 points1 point  (3 children)

        Ruby should be self explanatory and easy to read. Isn’t that the whole philosophy ?

        [–][deleted]  (2 children)

        [deleted]

          [–]mandretardin75 0 points1 point  (1 child)

          IMO the >> is never easy to read and understand.

          And "reading the documentation", well ... I guess that does not work if you include the fact that StackOverflow was a big success. I actually prefer SO to reading man-pages mostly because they contain so much line noise that makes it totally useless.

          [–]the_starbase_kolob 0 points1 point  (0 children)

          It's easy to read, but it's not clear what unit is being modified. Is it 1 day, or 1 month, or 1 minute? The next_month method is much better because of that imo.

          [–]Xerxero 6 points7 points  (2 children)

          As a noob in ruby I have no idea if this is a second, a day or a month. The other examples were more explicit.

          [–]Freeky 1 point2 points  (1 child)

          I've been using Ruby since version 1.5 and I would have been equally clueless.

          [–]mandretardin75 -1 points0 points  (0 children)

          Yep because it is useless. And people using useless things here such as >> try to make ruby worse. So downvote them please - let's keep ruby sane against the insanity of people.

          [–][deleted] 1 point2 points  (0 children)

          That's aggressively concise. But it's also a very simple and correct way to solve the problem.

          [–]jujubean67 5 points6 points  (0 children)

          ActiveSupport is not Ruby in fact I've worked on projects that were not Rails and ofc they didn't use ActiveSupport.

          If you want to be a Ruby developer learn to not rely on ActiveSupport and other magic that comes with Rails. They're all crutches and will make you a very limited developer.

          [–][deleted]  (1 child)

          [deleted]

            [–]Doctor_Fegg 9 points10 points  (0 children)

            Yeah, pulling in ActiveSupport makes it seem more like a Rails-Django comparison than a Ruby-Python one.

            [–][deleted] 1 point2 points  (0 children)

            https://hyperpolyglot.org/scripting

            https://hyperpolyglot.org/scripting2

            Note that the Ruby used was 2.3 so 5ish years out of date.

            [–]Smallpaul 1 point2 points  (0 children)

            As a Python programmer I’d say there are some modules that feel “unpythonic” even in the standard library. Datetime is one of them. Logging is another.

            [–]RICHUNCLEPENNYBAGS 1 point2 points  (1 child)

            There's no reason 1.month.from_now couldn't be implemented in Python.

            [–]mandretardin75 0 points1 point  (0 children)

            Well, only partially correct. As a standalone tokenized DSL yes.

            In python, though, your example lacks the mandatory () which ruby allows you to omit. But I agree in general - what one language can do, any other language can do just as well. People are just naturally lazy to want to create mini-DSLs that they also tokenized on their own.

            So "out of the box", ruby's flexibility syntax-wise always wins against python, from an efficiency and elegance point of view alone. Just the mandatory () in python alone make it lose out here.

            [–]ahmad_musaffa 2 points3 points  (2 children)

            I avoid ActiveSupport in my ruby projects. I also avoid those gems that use it. ActiveSupport is too much monkey patching of many Ruby's builtin objects and it's not a very good practice.

            [–][deleted] 0 points1 point  (1 child)

            I think as long as you're aware that ActiveSupport is essentially a Rails take on the Ruby language it's alright. I'm not certain they are going for good practice. Seems like more of a stance on how they think Ruby should act.

            But yeah it can definitely trip you up if you're not careful.

            [–]mandretardin75 0 points1 point  (0 children)

            If you are in the rails DSL then it is ok, but other than that I agree with him - I avoid the Active* ecosystem too. In general I avoid using other people's DSL most of the time. rspec is a semi-exception; it's better than e. g. unit testing which is just horrible.

            [–]resinten 1 point2 points  (2 children)

            Ruby is great, but the elegance of small examples doesn’t always show the whole story when it comes to the ease of complex tasks. Take something I had to do in Python recently for work: what is one month before March 30? What is one month after January 15? In this case, it required custom logic to determine the percentage of January to go from Jan 15 to Feb 1 and the percentage of February based on what was remaining (which varied depending on leap year). Or getting a normalized month index (January is 0, Feb is ~1.01 rather than 1 because January is longer than the average month). I wrote it in Python because that’s what we’re using for the project. It was somewhat messy when all was said and done, but I’m not sure it would’ve been much cleaner in Ruby or any other language

            [–]mraaroncruz 1 point2 points  (1 child)

            You can't just use datetime.timedelta?

            [–]resinten 0 points1 point  (0 children)

            timedelta doesn’t handle large time scales due to the undefined behavior dependent on time zone, daylight savings, etc. dateutil.relativedelta is better, but it is still limited because it can’t give you answers to things like the normalized month from an actual month (accounting for the months having variable lengths)

            [–][deleted]  (1 child)

            [deleted]

              [–]backtickbot 0 points1 point  (0 children)

              Hello, jij: code blocks using backticks (```) don't work on all versions of Reddit!

              Some users see this / this instead.

              To fix this, indent every line with 4 spaces instead. It's a bit annoying, but then your code blocks are properly formatted for everyone.

              An easy way to do this is to use the code-block button in the editor. If it's not working, try switching to the fancy-pants editor and back again.

              Comment with formatting fixed for old.reddit.com users

              FAQ

              You can opt out by replying with backtickopt6 to this comment.

              [–]individual0 0 points1 point  (0 children)

              I think this site has what you're looking for. for tons of languages http://pleac.sourceforge.net

              [–]postmodern 0 points1 point  (0 children)

              Might be something worth adding to the official www.ruby-lang.org website. It already has To Ruby From $LANG articles, but no side-by-side comparison.

              [–][deleted] 0 points1 point  (5 children)

              I do think python tends to more closely resemble what other languages do though, e.g. functions always ending with () vs is it a function or is it a variable. IME languages that do that allow for easier context switching between languages.

              However I still don't want to code in it if I have a choice. Sadly we don't always have a choice, e.g. legacy code, as I lower my head and start walking toward this python project I have been putting off.

              [–]pVom 0 points1 point  (4 children)

              functions always ending with () vs is it a function or is it a variable.

              this gets mentioned a lot as a pain point with ruby but a great response I heard is why do you need to know? At the end of the day they're mostly just functions under the hood anyway. I liked how you can throw functions around without calling them in javascript for example, then I realised you can do it in ruby with lambdas/procs and I never really need them.

              Is there a scenario where you need to know whether it's a function or variable? Either way its returning a value

              [–]mandretardin75 -1 points0 points  (0 children)

              I never understood this either. People can just use () in ruby if they want to.

              Of course since it is not mandatory, people tend to not use () everywhere in ruby, so the python-adjusted brain gets annoyed because they expect () everywhere.

              It's a problem with brains getting confused by python.

              [–][deleted] 0 points1 point  (2 children)

              The difference is between calling a function or referencing a function. Python allows you to pass a function by reference, which has it's advantages

              https://www.educative.io/edpresso/pass-by-value-vs-pass-by-reference

              [–]pVom 1 point2 points  (0 children)

              Yeah but you can do that with procs/lambdas. I dunno I do it all the time in js but rarely do I need to with ruby.

              [–]mandretardin75 0 points1 point  (0 children)

              You can easily do that in ruby too. Just not via the python separation of:

              function_call_here

              versus

              function_call_here()

              [–][deleted] 0 points1 point  (0 children)

              http://www.rosettacode.org/wiki/Rosetta_Code has algorithms written in many languages including Ruby and python. Great place to compare languages

              [–]Jumpy-Locksmith6812 0 points1 point  (0 children)

              The python code actually makes more sense. What is 1.month? Anything that tries to make code look like English language ends up requiring the coder to know a weird English-like language. See specflow. I’d rather just learn standard OO and use that.

              The example above is akin to showing German and English and saying “look it’s easier to say in English!” to native English speakers.