[HN Gopher] To Ruby from Python
___________________________________________________________________
To Ruby from Python
Author : mariuz
Score : 182 points
Date : 2022-07-16 06:51 UTC (16 hours ago)
(HTM) web link (www.ruby-lang.org)
(TXT) w3m dump (www.ruby-lang.org)
| by_the_bay wrote:
| One of my biggest complaints about Ruby is that that it's so much
| harder to drop into a debugger. In python it's as easy as import
| pdb; pdb.set_trace(), but for ruby (at least the versions on our
| build systems), you need to figure out how to add the dependency
| for pry/byebug first which is non trivial.
| tomstuart wrote:
| A fair complaint, but FYI it's outdated as of Ruby 3.0
| (released in 2020) which includes the `debug` gem [0]. So in
| Ruby 3.0 onwards it's as easy as `require 'debug'; debugger`
| just like you want. Hopefully your build systems will upgrade
| to a newer Ruby before too long.
|
| [0] https://stdgems.org/debug/
| zem wrote:
| as someone who has used ruby for years, and more recently got a
| job working in python, I think the most significant difference
| between the two languages is how they handle imports.
|
| in python every file is also a module, and all imported symbols
| are namespaced within that module (unless you deliberately use
| "import *" to bring them into the current module's namespace). so
| you can define function foo in module bar and use it via "import
| bar; foo.bar()".
|
| in ruby, modules/namespaces and files are two entirely orthogonal
| concepts; you define a module by enclosing code in a "module Foo;
| ...; end" block, and any file can open up the same module and add
| stuff to it. when you import a file it adds everything within it
| to the current global namespace, which makes it really hard to
| read a piece of ruby code and see where everything within it was
| defined.
|
| for the most part where ruby and python differ I prefer the ruby
| way, but I feel like automatically namespaced imports is
| something python got right, and was a really big miss for ruby.
| ufmace wrote:
| It's a possible smell in Ruby all right. Ideally, every file
| has its code in classes or modules that match the file name, so
| require 'foo' brings in the class Foo and nothing else. But
| it's possible to do some really ugly hacky stuff, so it more
| becomes please don't actually do that in a large production
| codebase.
|
| Python's default of namespacing imports is nicer all right,
| though I've seen a decent amount of Python code in the wild
| that has a dozen import * at the top of every file so that grep
| is the only way to find out where a function is actually
| defined, just as bad as Ruby.
| choward wrote:
| Ruby modules and requires effectively just concatenate a bunch
| of files that have globals in them and have nothing to do with
| real modules.
| mountainriver wrote:
| Agree Ruby code is super hard to understand, this seems largely
| overlooked by the community
| gls2ro wrote:
| (out of curiosity) What is hard to understand about Ruby?
| bcbrown wrote:
| Of the languages I've used in anger, Ruby is perhaps my
| favorite language to write code in. I think Python and Java
| are both easier to use in a large shared codebase, and one
| of the biggest reasons is that it's sometimes a lot harder
| to see where a method is defined in Ruby. Being able to use
| method_missing to automatically build a wrapper class or
| shim is super easy and pretty cool, but it can make it much
| harder to piece things together when debugging.
|
| I worked at a company that had a codebase split fairly
| evenly between Ruby, Java, and Python. The Ruby stuff was
| the hardest to understand, and I think it was primarily
| because of using patterns around dynamically method
| definitions.
| dolni wrote:
| One thing that drives me up a wall about Ruby (versus
| Python) is that function and method calls have basically
| zero context so you have _no idea_ where a piece of code
| actually lives without investigating or relying heavily on
| IDE features.
|
| Call a method on the current object? You just punch in the
| method name. There's no leading `self.` to indicate you're
| interacting with this class.
|
| If you require a library, the required code can be
| literally anything. Namespacing of the classes and
| functions is optional. Hopefully the library author did
| something reasonable. And even if they did, that
| namespacing isn't gonna match your require statement.
|
| Python's explicitness around this stuff is absolutely a
| breath of fresh air compared to Ruby's wild west approach.
|
| I also gotta say I'm not a fan of the fact that there tend
| to be one or two method aliases for lots of stuff in the
| standard library. It makes code easier to write but harder
| to read. As an example: the Array class has push, append,
| <<, unshift, prepend, and insert methods. Append is
| sensible. Do we _really_ also need it to be called push?
| and do we _really_ also need <<?
|
| Prepending is an uncommon enough operation that
| "array.insert(0, object)" should have been sufficient.
|
| I understand the intention behind Ruby's design decisions
| but I personally feel they do programmers a disservice.
| Writing (or even reviewing) Ruby without a featureful IDE
| is an absolute chore for projects of any appreciable size.
| gls2ro wrote:
| First, I do agree that Ruby ecosystem could do some
| things better and IMO in the last year or so there are
| some good projects happening in this space.
|
| Second, I cannot refute your arguments. That is because I
| see them more of a personal preference or somehow
| expectations based on your programming history (I might
| be wrong of course as I don't know your programming
| history). As Ruby feels similar with other programming
| languages I think some kind of expectations of how things
| should be kick in. But Ruby has a specific design that is
| for example focused on "brevity" or "beauty" among
| multiple other thigs.
|
| I worked so far in the last 15 years in multiple
| codebases in Ruby: large Rails apps, Sinatra apps but
| also smaller webapps. In all kind of combinations some of
| them I built and maintained alone and some of them were
| built in a team.
|
| This being said, I don't remember a time when we have a
| big name conflict because we used a couple of gems and
| they were colliding.
|
| I do remember when some colleagues were over using meta-
| programming too much or changing default behaviour of
| stdlib. But this can be fixed with coding guidelines and
| I take imposing coding guidelines over removing these
| features from Ruby as sometimes they make more sense than
| anything else.
|
| Regarding ".self" I don't feel the need to use it. Once I
| got the call hierarchy I prefer not needing to write
| "self" where it is not needed.
|
| But also in Ruby everything* is an object thus I feel
| that self is a bit more powerful so it should be used
| when when it is really needed like when defining methods
| and you want to indicate where that method belongs.
|
| Regarding having multiple ways of doing the same stuff in
| stdlib, here we diverge as I prefer this diversity. I
| really like that we are multitudes in this community so
| code can be written in multiple ways, it is for me almost
| like a form of art when I read some case and I see how
| expressive can it be and how easy it is to get what it
| does even if it uses a different std method than I
| normally use.
|
| I think if you want to get Ruby you should start by
| thinking that Ruby is a programming language created
| (IMHO) with the intention to let you express yourself but
| also make it so that other people should easily
| understand it.
|
| It also worth reading this beautiful essay by the creator
| of Ruby: https://www.oreilly.com/library/view/beautiful-
| code/97805965... (sorry I could not find a direct link
| unwalled) and from there you will get a glimpse of why
| Ruby is in a specific way and see if you agree or not
| with that.
|
| For example regarding your point with no leading self,
| Matz says in that essay "programs should ideally contain
| no unnecessary information" thus a lot of what you see in
| Ruby including having prepend instead of "insert(0,
| object)" is a manifestation of that.
| atmosx wrote:
| It can be, more than other languages, but doesn't "have" to
| be. Complex code is a smell.
| entropie wrote:
| Meta programming stuff can be very confusing for non native
| rubyists. Generally thats something one should avoid in
| shared/production codebases.
| lgreiv wrote:
| As someone with a bit more of a decade of Ruby
| experience: meta programming can be very confusing for
| native rubyists, too. There is a place for it (my
| personal take would be that this place is usually
| libraries/gems, e.g. if they need to be flexible to adapt
| to the consumer's project), but it's usually not code
| that needs to ,,convey a story" (usually business logic)
| or needs to be debugged/observed.
| tomc1985 wrote:
| I have never had this issue, other than with some of its more
| complicated constructs (like class << self).
|
| And amongst the community, this is not a complaint I hear
| very often.
|
| I still think of Ruby as the language that maps closest to my
| thought process when programming.
|
| What is troubling for you?
| lloeki wrote:
| The tradeoff is that you don't get to have open classes with a
| module oriented approach.
|
| Shameless plug: toyed with the idea of imports and "packages"
| in Ruby some time ago. Recent facilities in 3.1 (or 3.2?) could
| make the implementation even easier.
|
| https://github.com/lloeki/pak
|
| https://github.com/lloeki/ruby-package
|
| IIRC there's an issue somewhere at bugs.ruby-lang.org about
| that
|
| EDIT: OMG 8 years ago! /me screams
| dragonwriter wrote:
| > The tradeoff is that you don't get to have open classes
| with a module oriented approach.
|
| A module oriented approach could still have open classes, and
| if you did an imported module could still mess with classes
| in other imported modules (it would just also have to import
| them.)
|
| In fact, you can set variables in other modules and members
| (including methods) of other classes this way in Python.
| zem wrote:
| i like that! it definitely makes things cleaner in terms of
| being explicit about where everything comes from.
| typeofhuman wrote:
| > so you can define function foo in module bar and use it via
| "import bar; foo.bar()".
|
| Wouldn't this be "import bar; bar.foo()"?
| heartbreak wrote:
| Yes, it looks like OP had a typo.
| 86J8oyZv wrote:
| In Ruby it's "require" rather than "import." But it would be
| more like "require bar; foo()".
|
| However, Ruby _does_ have auto-loading conventions. So you
| could define "module Baz{ module Bar { def foo end; } }" in
| "baz /bar.rb" from the root of your project. You should then
| be able to call "Baz::Bar::foo()" from any other file in your
| project structure without a "require" at all. This is not
| standard Ruby IIRC, but Rails and other frameworks use it.
| gls2ro wrote:
| There is a gem that does that used by Rails and multiple
| other gems:
|
| https://github.com/fxn/zeitwerk
|
| It is pretty easy to set it up in any Ruby project.
| dragonwriter wrote:
| it would actually be: require 'bar'
| foo
|
| because require is a regular method and the argument is a
| string (I mean, you could pass _bar_ without quotes if the
| string was in a variable called _bar_ , but that's not the
| scenario being discussed.)
|
| > However, Ruby does have auto-loading conventions. So you
| could define "module Baz{ module Bar { def foo end; } }" in
| "baz/bar.rb" from the root of your project. You should then
| be able to call "Baz::Bar::foo()" from any other file in
| your project structure without a "require" at all. This is
| not standard Ruby IIRC
|
| autoload is a Kernel method in Ruby core, so it is standard
| Ruby, but you have to explicitly register a file to be
| automatically loaded when a particular method is
| referenced.
|
| Some systems additionally include code that does this for
| source files based on path.
| khaledh wrote:
| > You should then be able to call "Baz::Bar::foo()" from
| any other file in your project structure without a
| "require" at all.
|
| IMO, this is a downside rather than an upside. It's
| optimizing for writing rather than reading. This hurts
| understandability for someone who is not familiar with the
| code base.
| jonnytran wrote:
| IMO, Ruby optimizes for reading. You simply cannot write
| concise code in Python as in Ruby. One reason (of many)
| is because of all the import statements required in
| Python. In Ruby, there is often only a single require
| statement, or maybe none at all, at the top of a file.
|
| The difference is convention over configuration. In Ruby,
| if you know the convention, then you know exactly where
| everything is defined without needing to read it. In
| Python, you must read all those import statements to know
| where something is coming from, not to mention write them
| in the first place.
|
| And if you really need to know where something is
| defined, you simply ask it. puts
| obj.method(:foo).source_location
|
| So IMO, Ruby optimizes for both reading and writing.
| zem wrote:
| right, that was my mistake
| bamboozled wrote:
| Forget all of it and use Go :)
| entropie wrote:
| Probably not a bad advice.
|
| Most of the ruby enthusiasts I know from the old days took a
| deeper dive into go.
| goatlover wrote:
| I would think Elixir or Crystal would have been the more
| natural transistion for Rubyists. Or even Common Lisp. Go's
| philosophy is very much at odds with Ruby's.
| jonnytran wrote:
| The only thing I disliked more than moving from Ruby to Python
| was moving to Go. All the things I love about Ruby are the
| antithesis of Go.
| x86x87 wrote:
| vault wrote:
| deleted
| greenpeas wrote:
| What do you mean?
|
| > When tested for truth, only false and nil evaluate to a false
| value. Everything else is true (including 0, 0.0, "", and []).
|
| In ruby only `false` and `nil` evaluate to false values. 0, [],
| "" all evaluate to true when used in `if` statements. In python
| (just like in C and JS) many things evaluate to false
| (including 0, 0.0, "", and []).
| vault wrote:
| Ah sorry I read "Unlike Ruby, in Python" instead of "Unlike
| Python, in Ruby"
| thih9 wrote:
| This page is old [1], is there any reason or context regarding
| why it is interesting now?
|
| [1]: Archived in 2006:
| https://web.archive.org/web/20060925032432/https://www.ruby-...
| Kwpolska wrote:
| The page has been slightly changed since then, but it is still
| quite outdated. Python 3.6 (2016) has formatted strings, and
| new/old-style classes thing isn't relevant at all since Python
| 3, but wasn't that much of a deal with Python 2 at the end of
| its lifetime (~everything was new-style by then).
| sitkack wrote:
| Ruby is a neat language that I don't know very well. Blocks
| are nice. The pattern matching in Python 3.10 compels me to
| stay.
| weaksauce wrote:
| ruby has some nice pattern matching too
| https://rubyreferences.github.io/rubyref/language/pattern-
| ma...
|
| not sure if python has better matching though but the ruby
| stuff is pretty compelling.
| mahathu wrote:
| I love Python and use it pretty much anywhere I can, especially
| as it's ubiquitous in scientific computing. Is there a good
| reason to switch to Ruby except to try something new?
| linuxftw wrote:
| As a non-ruby user, from my POV ruby is primarily related to
| webapps. While it's possible to use it for other types of
| software, nobody really does, except possibly people that
| already maintain large codebases of ruby webapps.
| nixpulvis wrote:
| I would claim that Ruby as a language is much nicer to use,
| however it has less support for data science and other things
| which Python is much more well known for. If you ported over
| some libraries, you might find you like Ruby more in the end.
| doix wrote:
| My biggest gripe with Ruby is how much syntax is optional and
| the "accepted" conventions by the community are to leave out
| a lot of optional syntax.
|
| The worst offender (in my opinion of course) is leaving out
| of empty parentheses on method calls. It makes it impossible
| to know if something is a property or a function. The
| argument is that it doesn't matter if it's a property or a
| function, but I feel like it makes it very difficult to
| reason about performance. If I know something is a function,
| I'll look at the function and see what the performance
| implications are. Where as if something is a property, I
| assume it's "free" to access. This doesn't hold when reading
| Ruby code, and I basically have to look up everything all the
| time.
|
| Just my opinion as someone that had to switch between
| python/ruby/perl to maintain tools written during different
| decades.
| nixpulvis wrote:
| Always use parens. That's my rule.
| ByteJockey wrote:
| > but I feel like it makes it very difficult to reason
| about performance
|
| This seems like a form of premature optimization.
|
| I mean, you're not wrong technically, but if you were
| exceptionally performance concerned, you probably wouldn't
| be using ruby.
|
| If you're just regular performance concerned (i.e. you want
| to stop pathological behavior in the hot loop), you're
| really only concerned about 1-2% of your code. You wait
| until it's an issue, run a profiler over your code and
| optimize the couple of parts that are causing the issue.
| floodedchip wrote:
| What do you mean by "property or function", though?
|
| There are no properties or functions in my view--only
| messages. object.message sends message to object, which
| object may or may respond to.
| dehrmann wrote:
| It's the same in Python. Methods just happen to be
| callable properties.
| wodenokoto wrote:
| > There's only one kind of list container (an Array), and it's
| mutable.
|
| What are the other kinds of list containers in Python? I only
| know of `list()`/`[]`, but maybe I just don't realize that some
| other thing I use is also a list container.
| zbentley wrote:
| array.array, as another commenter mentioned; numpy.array is
| popular for performance-oriented code (but not in the stdlib);
| collections.deque; queue.Queue; tuple; struct (though it's a
| bit of a pain to make one behave in an array-like way and is
| usually better to use array.array); heapq; and
| multiprocessing.shared_memory.ShareableList.
|
| Out in pypi there are many additional esoteric list-like data
| structures: bitarray is one of my favorites, and there's also
| awkward-array, cyarray, tinyarray, fixedlist, blist, bigarray,
| sortedcontainers, and many many more.
| uranusjr wrote:
| I'm guessing they're implying tuple, it's pretty common to
| consider that type as "immutable list" (although personally I
| very much dislike this categorisation)
| masklinn wrote:
| > although personally I very much dislike this categorisation
|
| It's not a categorisation, it's literally the nature of the
| thing in Python. And while I agree that it's distasteful the
| error was in the original introduction.
|
| As things are, python tuples are immutable sequences with all
| that implies. They are iterable, indexable, sliceable, ...
| baq wrote:
| Immutability crucially allows for hashability, so you can
| use (some) tuples as dict keys.
| kevin_thibedeau wrote:
| array.array
| nixpulvis wrote:
| > The usual-style comments on the line(s) above things (instead
| of docstrings below them) are used for generating docs.
|
| This is another thing about Python that I find very unsettling
| and wrong.
| scotty79 wrote:
| For me there wasn't ever question of "How?" only "Why?".
|
| One time I landed on Ruby project and I didn't have any trouble
| fixing bugs and implementing minor functionalities without really
| learning Ruby only knowing some Python.
| cortesoft wrote:
| I feel similarly about python. I use ruby all the time, but can
| do things in Python just fine, especially if I have an existing
| code base that I am working on.
| scotty79 wrote:
| Tensorflow? Numpy?
|
| No idea what else might be the reasons to learn Python when
| you know Ruby.
| mark_l_watson wrote:
| I loved coding in Ruby. I also wrote a Ruby book for Apress, my
| last book for a major publisher before starting to self publish
| on leanpub.com/u/markwatson
|
| Two factors made me leave Ruby behind: I am somewhat known for
| Common Lisp, and so CL jobs would come my way. Also, in the last
| 8 years, a huge amount of my work has been in deep learning and
| Python wins there.
|
| Anyway, Ruby was designed to make programmers happy, and it is a
| big success at that.
| brudgers wrote:
| Genuinely curious, would Ruby be your desert-island-with-only-
| one-language language?
|
| If not, what would your language be?
|
| Of course, you could - at least in theory - take any language
| and implement some other in it...so I guess maybe there's a
| question of is it easier to write Lisp in Ruby or Python in
| Lisp, etc.?
| mark_l_watson wrote:
| That would be Common Lisp.
| x86x87 wrote:
| probably you would want C on a desert island. you could write
| your own ruby or python or anything in it.
| itake wrote:
| > Anyway, Ruby was designed to make programmers happy, and it
| is a big success at that.
|
| I switched to golang from ruby and I definitely don't miss the
| ctrl+f hunts to figure out the source code of functions in ruby
| programs. its even worse when dynamic programming is used to
| create 'helper' methods (e.g. `{attribute_name}_changed?`) that
| you have to read through lines and lines of code to find
| anything.
| jkogara wrote:
| I use ctags that are rebuilt in the background on each commit
| or pull, makes find source code of definitions trivial.
| jshen wrote:
| I find most things by jumping into pry at a break point and
| inspecting it. Works really well, but isn't something that's
| common in other languages so people don't think to do it.
| msbarnett wrote:
| If anyone very finds themselves hunting around for a method
| definition like this,
| method(:blah_changed?).source_location
|
| is your new best friend.
| [deleted]
| Hackbraten wrote:
| I tried for many years to be happy with Ruby.
|
| Ended up leaving it behind because more often than not, when I
| revisited a Ruby codebase after a while, Bundler would complain
| and tell me that I'm supposed to run `bundle install`
| something, and sure enough, doing just that sent me into a
| rabbit hole of errors.
| gls2ro wrote:
| I am sure it will not bring you back :) but in case others
| might read this and have the same issue the solution is to
| config bundler to install the gems locally inside a project
| folder (I usually go for ./vendor/bundle) and the add that to
| .gitignore
|
| This way if you work with multiple projects each using
| different Ruby versions and different gem versions you don't
| keep to keep reinstall the gems whenever you switch the
| directory.
| jbverschoor wrote:
| Gems are versioned already, and if you're working with
| different Ruby versions, your gems are already isolated to
| that version.
|
| No need to vendor gems..
| jbverschoor wrote:
| Gems are versioned already, and if you're working with
| different Ruby versions, your gems are already isolated to
| that version.
|
| No need to vendor gems.. Vendoring millions and millions of
| duplicate files is for the node crowd.
| theonething wrote:
| > Vendoring millions and millions of duplicate files is
| for the node crowd.
|
| and PHP
| LV123 wrote:
| "sure enough, doing just that sent me into a rabbit hole of
| errors"
|
| I did that exact thing in a project last weekend, and ended
| up spending 5 hours trying to fix the horrible mess that
| ensued. I only tried doing this in the first place because
| bundler errored out on installing one of the gems, and I
| figured a "clean" local setup would fix things.
|
| For some reason the project still wanted to use global
| gems, and when I tried to delete them to force it to use
| local gems I broke everything. In the end I just installed
| RVM with a clean version of Ruby and let it use global
| gems.
|
| I'm sure I did it wrong, but the errors I got were just
| insane. I couldn't delete gem X because I had gem Y
| installed, I couldn't delete gem Y because I DIDN'T have
| gem Z installed. I couldn't install gem Z to delete Y to
| delete X because my installed version of gem Q didn't match
| the version bundler wanted, but I couldn't install a new
| version of Q because of reasons...
|
| After reinstalling the exact same gems (through RVM instead
| of the apt-get version of Ruby I had before) things still
| didn't work, and it took me quite a long time to figure out
| that the error "your version of [some YAML gem] is wrong"
| means that you have to add a line of Apache config telling
| Passenger to use Ruby.
| revscat wrote:
| > I did that exact thing in a project last weekend, and
| ended up spending 5 hours trying to fix the horrible mess
| that ensued.
|
| What gem(s) were giving you issues? I can try and
| replicate it if you'd like.
| gls2ro wrote:
| I am sorry for your experience with this.
|
| I am just trying to understand your case. So if you have
| a Gemfile in your folder and then execute something like
| bundle config set --local path "vendor/bundle"
|
| Then all gems should be installed in ./vendor/bundle.
|
| I am not sure how Passenger works (as I am mostly using
| Puma). I am assuming based on what you wrote that the
| issue was with the gem passenger itself which is used by
| the Apache config and it is not a library used by your
| project.
|
| I don't think the issue you encounter is representative
| to Ruby and it's ecosystem. I think any module loaded to
| Apache will probably need a way to know how to load some
| other modules and probably passenger (via Apache config)
| needs to know where to find the dependencies it has.
| Passenger is a web-server so it has its own dependencies.
|
| My suggestion was about the dependencies of your own
| project.
|
| I am usually doing projects with Rails and Sinatra + Puma
| + Nginx or Apache and in both of them with the setup I
| shared I did not encountered any problems releasing the
| project in production with bare metal configuration (via
| Capistrano for example) or using Docker.
|
| I am not saying that my experience is representative for
| everything in Ruby ecosystem. I started using Ruby in
| 2007 with Ruby 1.8 and I do agree that we had some rough
| years in the ecosystem specially when working on multiple
| projects simultaneously.
|
| But now, my experience is a breeze.
|
| On a tangent, I have more problems with npm/yarn than
| with gems. For example I just started to upgrade an old
| Rails app to Rails 7 and suddenly on my Mac OS a npm
| package needs some kind of Python version with some
| libraries that in turn seems to require some other stuff.
| Even if I am more like a dinosaurs and prefer to run
| locally all projects (thank maintainers for asdf) for
| this one I let it go and put it in docker :)
| LV123 wrote:
| Thanks, I'll give it another try some day and try
| switching to local gems. I used the exact command you
| suggest and it didn't work, but I don't remember why.
| Unfortunately I didn't keep all the logs, so I don't
| remember exactly what all the errors were, but I think
| Passenger was the cause of about half of my woes and I'll
| look into replacing it.
|
| Bundler was pretty damned useless though, I've had a much
| worse experience with that than I've ever had with yarn,
| pip or npm. It really shouldn't be necessary to nuke the
| whole Ruby installation to do a clean install from a
| Gemfile, and the errors it produces are extremely
| misleading and unhelpful.
|
| I'm not really a Ruby dev, I just inherited an ancient
| Rails project and had to make it work (upgrading from
| Rails 4 to 7 in the process), so the project setup is
| less than ideal. I'm sure a lot of my problems were self-
| inflicted ;-)
| gls2ro wrote:
| Thank you for replying to give more context.
|
| You have some courage to go to a Ruby project and try to
| upgrade Rails from 4 to 7. I hope it will go as smoothly
| as possible. Props to you!
|
| I am not sure if it helps and maybe you know these, but
| just in case here are 3 URLs I keep at hand when I
| upgrade Rails:
|
| 1. https://railsdiff.org (where it shows diff from
| sources)
|
| 2. https://www.fastruby.io/blog/tags/upgrades (they have
| some great articles in cases of some upgrades)
|
| 3. https://guides.rubyonrails.org/v6.1/upgrading_ruby_on_
| rails.... (there is page for each version just replace
| v6.1 with the major version that you need)
|
| And also if you have not already started may I suggest
| you don't go directly from Rails 4 to Rails 7 but just
| try to go to each major(ish) version:
| Rails 4.0 -> 4.1.x Rails 4.1 -> 5.0.x Rails
| 5.0 -> 5.1.x Rails 5.1 -> 5.2.x Rails 5.2
| -> 6.0.x Rails 6.0 -> 6.1.6.1 Rails 6.1 ->
| 7.0.x
|
| For each version there is an upgrade page. Eg:
|
| - https://guides.rubyonrails.org/v4.1/upgrading_ruby_on_r
| ails....
|
| - https://guides.rubyonrails.org/v5.0/upgrading_ruby_on_r
| ails....
|
| - https://guides.rubyonrails.org/v5.1/upgrading_ruby_on_r
| ails....
|
| You might want to give a try to this gem:
| https://github.com/fastruby/next_rails. I did not used it
| so far but I would have a Rails 4 app I will probably try
| to use it.
| LV123 wrote:
| Thank you! Those resources would have been incredibly
| helpful 6 months ago, haha.
|
| It was less courage and more desperation, as the project
| was running on a server which died before Christmas and
| we needed it back up before January. The last major
| change to the project was ~6 years ago and nobody had
| touched it in ~5 years, so there was nobody around who
| had the slightest idea how it worked. Props to Rails for
| just _working_ for that long with practically zero
| maintenance. In case you 're wondering why we had
| critical software running on a single server with no
| maintenance: student organization.
|
| We weren't able to find/install an Ruby installation old
| enough to run the project, so we decided to just upgrade.
| It was the brute force approach of "run the project, see
| what error pops up, google the error, fix the error,
| repeat". In hindsight, this wasn't a good idea and I
| could probably have found the right Ruby version with a
| bit more digging, but it works at least.
|
| It's just a handful of pages with minimal code though, so
| now that things are less desperate I'm considering just
| starting from scratch with a clean Rails install and
| manually recreating them. Just need to deal with the
| legacy database schema and make some changes to it.
| mpyne wrote:
| For what it's worth that's also been my experience with some
| Ruby projects I have. Usually bum-simple Jekyll web sites in
| response to a dependabot warning.
|
| It's almost always a fight to get going again and it seems so
| needless. Like just reinstall the gems from scratch if you
| need to, jeez, this isn't even a CI I don't need the gems to
| be literally identical to what was here a year ago, I just
| need "bundle exec jekyll serve" to actually do something...
|
| That all said I still like Ruby as a language, it brings the
| good stuff over from Perl while being as expressive as Python
| and pretty damn fast to boot. And I recognize Python also has
| similar dependency challenges. But this is very irritating.
| entropie wrote:
| > It's almost always a fight to get going again and it
| seems so needless
|
| Hm. I do ruby webdev stuff for over a decade now (first
| ramaze, hanami now) and use a self baked overlay that
| manages multiple hanami apps and capistrano to deploy them
| and shares plugins to all the webapps (like a blog
| component).
|
| I love it. Sure, there were problems with bundler and some
| with capistrano too but overall its very pleasant for me.
| weaksauce wrote:
| as an other perspective this happens because you are not
| pinning the versions correctly. your gemfile should have an
| explicit version of every major gem you use and the
| gemfile.lock should have the resolved dependencies already
| made out and committed. you should also have a particular
| version of ruby in mind and locked with a .ruby-version file
| in the project root. This should work flawless in all but the
| oddest edge cases.
| jspash wrote:
| Leave a javascript project for more than 2 weeks and you'll
| get the same thing.
| Taikonerd wrote:
| If you switched to Python, then you probably traded your
| `bundle install` errors for `pip install` errors ;-)
| fny wrote:
| Pip doesn't do dependency resolution either... I spent a
| day trying to pin down issues migrating a project from
| pipenv to poetry because poetry did not agree with pipenvs
| resolution.
| neeleshs wrote:
| AFAIK, pip does dependency resolution, you can disable it
| via --no-deps
|
| https://pip.pypa.io/en/stable/topics/dependency-
| resolution/
| fny wrote:
| Excuse me I should have said conflict resolution.
| [deleted]
| hawkeyedan wrote:
| Arguments about the "superiority" of Python vs Ruby always sound
| a bit like arguments about the "superiority" of Italian vs
| Spanish. If you squint a bit they're basically the same.
|
| (By that simile, Lisp would be Sanskrit?)
| thebigspacefuck wrote:
| True, but 85 million Italian speakers vs 500 million Spanish
| speakers so that tells you something. Sure the Roman Empire was
| big back in the day but the time has passed.
| ptx wrote:
| > _You can read docs on the command line (with the ri command
| instead of pydoc)._
|
| I've been using Python for a long time, but somehow I never
| learned about pydoc. It looks like a pretty handy tool!
| winstonsmith wrote:
| >[In Ruby] There is good support for functional programming with
| first-class functions, anonymous functions, and closures.
|
| This seems like a blatantly false claim to me since as a Python
| programmer forced to use Ruby for Sketchup, I have been
| frustrated by the lack of first-class functions in Ruby.
| tomstuart wrote:
| I'm interested to learn what "first-class functions" means to
| you. Ruby has both `Proc` and `Method` which would appear to
| qualify. Is your frustration that you can't `def foo ... end`
| and then use bare `foo` to refer to it as a value (vs invoking
| it)?
| winstonsmith wrote:
| My frustration is that you can't pass foo as an argument to
| another function.
| tomstuart wrote:
| Right, I see, because you have to say `method(:foo)` or `->
| { foo }` or whatever. To me this is an acceptable syntactic
| trade-off in exchange for being able to invoke the method
| with bare `foo` (i.e. variable reads and method calls look
| the same) but I can see from other comments here that some
| people dislike that ability anyway. Vive la difference!
| chrisseaton wrote:
| But you can. Method objects, proc objects, lambda objects,
| blocks, you've got a wealth of options here in Ruby.
| submeta wrote:
| Ruby is a beautiful language, but it lost the race against Python
| long ago. - When I first looked into both some ten years ago, I
| was undecided what to choose. But even back then googling
| problems led to much more professionally written blogs / articles
| about Python. Articles about Ruby were not as profound. That's
| when I decided to go with Python. And it was the right choice.
|
| ## Edit
|
| What I miss in Python: Ruby always returns a value and does not
| change structures in place. For instance `data.sort()` in Python
| will return `None` and change the order in `data`. Ruby won't do
| that and will return a sorted copy. Like Scheme (a Lisp dialect).
| In Scheme methods changing data have an exclamation mark as
| suffix: `(sort! data)` vs `(sort data)`, and it will always
| return a value. Unlike Python.
| msbarnett wrote:
| What "lost"? They're both Top 10 most used languages with tens
| of thousands of open positions currently available for someone
| competent in either.
|
| Python's the more frequently used of the two industry-wide, but
| it seems like they both won, just with different crowds.
| dehrmann wrote:
| I think it's that Ruby has mostly been relegated to Rails,
| while Python sees use in backend systems, data science,
| scripts, and as a popular first language.
| disgruntledphd2 wrote:
| As a professional data scientist, I kinda wish ruby had won
| for this area, as it's much closer to R conceptually.
|
| Python is fine, the metaobject model is pretty nice, and I've
| stopped noticing the double underscores ;)
| tomstuart wrote:
| You may be making a point about what happens by default (and
| perhaps Ruby's similarity to Scheme?), but in Ruby you can also
| say `data.sort!` if you want the `data` array modified in-
| place. It's still returned, though.
| disgruntledphd2 wrote:
| The hardest thing for me to understand in Python was the
| baffling tendency of methods to return None.
| teddyh wrote:
| I think I have read somewhere that they return None in
| order to explicitly signal that the object has been
| modified in-place. For example, if you want to have one
| method which sorts in-place, and another which returns a
| sorted copy, if then both methods returned a sorted object,
| it would be too easy to mistakenly call one instead of the
| other, creating a bug which might not be found for years.
| cortesoft wrote:
| > Ruby always returns a value and does not change structures in
| place
|
| The not changing structures in place bit is only for std
| library things... nothing is stopping code you write from
| modifying structures in place.
|
| Ruby has the '! means it mutates' convention as well, and the
| built in methods use it (for example, .sort! on an array
| modifies the array in place just like your Scheme example).
| However, again it is just a convention... nothing stops a ruby
| developer from modifying something in place without a !, or
| making a method that ends in ! that doesn't modify in place.
|
| The common theme in Ruby is 'nothing stops you from...'
| revskill wrote:
| Ruby eventually failed in term of quantity of developers, means
| OOP will eventually died. It's not Ruby's fault, it's just the
| failure of OOP in general.
|
| My prediction, in about 4 years or more, OOP is just an abandon
| concept for all programmers.
| gls2ro wrote:
| Mind you that (let's say) the modern concept of OOP was
| invented around second part of 60s (with Simula I think) and I
| think functional a bit earlier maybe in the beginning of 50s
| (with LISP I think).
|
| Both paradigms have a lot of years of practice and saying that
| anyone of them will die in 4 years is I think a bit of
| exaggeration.
|
| Why do you think that in 4 years OOP will be abandoned by
| programmers? What is the basis for your assertion?
|
| I think it is more probable that we will have a kind of cross-
| pollination between these two paradigms with maybe newer
| languages (or evolving existing languages) to borrow concepts
| and best practices while still providing the core way to design
| solutions. This is already happening in smaller scale in
| multiple languages as far as I see it.
| goatlover wrote:
| Uh huh. And static typing will replace dynamic for all
| programmers, functional will replace all uses of imperative,
| nobody will use whitespace indentation, and all emacs users
| will switch to vim. Also, every programmer will abandon Windows
| and macOS for Linux.
| tomc1985 wrote:
| So, C++ and Java have just a couple of years of life left?
| damagednoob wrote:
| Not too mention C#, Python and for some, Javascript.
| mypalmike wrote:
| All doomed. Google and Amazon, for example, will rewrite
| their many millions of lines of Java and C++ in Haskell by
| 2026.
| amerine wrote:
| Ruby seems to have cemented itself in my head as one of my
| favorites. I've built a career from it and am eternally grateful.
| sinsterizme wrote:
| This is very good timing for me, I just left my python dev job
| and am starting a job where they use Ruby. I'm very excited to be
| using Ruby again, it's a much nicer language to use for a variety
| of reasons I can't possibly enumerate. Ruby's stdlib and
| surrounding documentation is pristine, I vividly remember being
| appalled when trying Python for the first time and thinking where
| the rest of it was. The major issue I find with Ruby (and that I
| saw mentioned elsewhere in this thread) are imports / requires,
| which is much too magical in Ruby; Python's import is way saner
| fny wrote:
| Ruby's imports aren't magical by default. Autoloading
| frameworks make them so.
| khaledh wrote:
| The fact that ruby makes this possible means the community
| will take advantage of it, to the point of abusing it
| sometimes. This hurts understandability of the code base. Too
| many times I would open a ruby code base and spend
| significant amount of time tracing where things are defined
| (mostly relying on suboptimal searching) because of the lack
| of explicit imports/requires.
| ysavir wrote:
| An easy way to do that is to use the Pry gem. If you're in
| a pry console, you can use `show-method Thing.foo` and it
| will show you the method, which file and line it's defined
| in, etc. Pry is a great tool and this feature makes is a
| blessing.
| Spivak wrote:
| Python can do this magic too and the community hasn't
| abused it. Every part of modules and module loading is
| swappble, mutable to the point where modules can be
| arbitrary classes if you want.
|
| It would be 2/10 difficulty to add transparent module
| autoloading to Python because you can just hook into module
| loading and arbitrarily modify or replace the module
| objects.
|
| You wouldn't even need a courtesy import because the main
| module is still a module.
| byroot wrote:
| Even without an autoloader, Ruby has a single global
| namespace, so you have access to everything that has been
| required at any point from anywhere.
|
| If anything autoloaders enforce that constant names match
| filenames, making it easier to locate the source.
| xavdid wrote:
| Ha, I just did the same thing. It's definitely a bigger shift
| than I expected!
|
| I think the biggest difference so far is the quality of dev
| tooling. Python's native type system has enabled a lot of
| really good editor functionality. Ruby has Sorbet, which seems
| good, but it's _much_ slower and more cumbersome. After a save
| to fix a red squiggly line, there's a 5 second delay before the
| typechecker / linter figures out the code has updated, run, and
| updated errors in-editor (note: this could be due to the size
| of the repo, but it's still a pretty tough experience)
|
| In the company codebase it's pretty well set up and VSCode come
| pre-configured. But yesterday I tried setting up a little ruby
| project on my personal machine and couldn't figure out the
| combination of extensions to make basic auto-complete and jump-
| to-definition functionality work at all. To their credit,
| Microsoft has made Python development incredibly
| straightforward by giving a One Best Way To Do It and making
| sure there's good LSP support.
|
| Python has its warts for sure, but I've grown to really
| appreciate the language and its ecosystem.
| lloeki wrote:
| For some reason it reminded me of _why's unholy:
|
| https://github.com/devyn/unholy/blob/master/README
|
| > You know, it's crazy that Python and Ruby fans find themselves
| battling so much. While syntax is different, this exercise proves
| how close they are to each other! And, yes, I like Ruby's syntax
| and can think much better in it, but it would be nice to share
| libs with Python folk and not have to wait forever for a mythical
| VM that runs all possible languages.
| tomc1985 wrote:
| That's funny.
|
| In a previous job I was the biggest Ruby supporter on a team of
| Pythonistas. To show them how similar the language was I
| translated a couple of their scripts from Python to Ruby... it
| was surprisingly easy and the linecount was about the same
| teddyh wrote:
| That is all good and well, but which was easier to read and
| debug?
| helge9210 wrote:
| On the surface, Ruby and Python are mostly equivalent languages.
|
| Internally, memory management is done differently, for example.
|
| Now add a magic of Ruby on Rails and ActiveSupport to one side
| and machine learning toolsets to the other.
| viraptor wrote:
| Not just on the surface. See the ruby to python bytecode
| compiler: https://github.com/whymirror/unholy
| mountainriver wrote:
| Really the only reason to use Python is ML, but that is the
| future of everything so....
| x86x87 wrote:
| nah. ML is not the future of everything. in fact I believe that
| as things are going to evolve ML as we see it today is going to
| be only a tiny fraction of what is going to be used
| goatlover wrote:
| > Really the only reason to use Python is ML
|
| Not the other scientific and statistical libraries?
|
| > but that is the future of everything so....
|
| So is fusion and flying cars. Maybe one day AGI will be here,
| but I doubt we humans will be using Python ML libraries at that
| point.
| jbverschoor wrote:
| I'm missing the best part - In ruby we have an intuitive and
| extensive standard library
| aendruk wrote:
| Of all measures to compare by that seems a particularly ill
| choice. One of the few things I know about Python is its
| longstanding reputation for having batteries included.
|
| (But yes, you can pry Enumerable from my cold, dead hands.)
| DonHopkins wrote:
| "Python is bash for mathematicians." -Michael Slavitch
| BiteCode_dev wrote:
| Python is used for Web dev (Django), geography (all SIG),
| system components (part of Unix), pen testing (E.G: scapy), 3d
| modeling (Blender), sysadmin (ansible), etc.
|
| I've been coded mostly in Python for 15 years and using the
| scientific stack is a very small parts of what people pay me
| of, if they ever do.
| DonHopkins wrote:
| You're misinterpreting that quote as criticism of Python
| instead of praise. He's not saying that's the ONLY thing that
| Python is good for.
|
| I've also been programming in Python extensively for at least
| 20 years, including web application servers like Zope and
| TurboGears, embedding and extending apps and tools with the
| Python/C API and SWIG like SimCity, Gnu Radio, Big World
| MMPORG, robotics, simulations, Blender, Houdini, user
| interfaces like Tkinter and PyGTK and Sugar, XML processing,
| OLE integration, BeautifulSoup web page scraping, image
| processing, character animation, speech synthesis, system
| administration, infrastructure as code, machine learning,
| etc.
|
| Python is of my primary programming languages, and I love it.
|
| It's a GOOD thing that mathematicians use Python instead of
| Bash!
| BiteCode_dev wrote:
| Mathematicians never used bash. Most of them didn't even
| touched the command line 10 years ago.
|
| I'm not the one misinterpreting.
| DonHopkins wrote:
| It's pretty clear and not subject to interpretation that
| I never claimed mathematicians ever used bash, but just
| the opposite: they use Python instead.
|
| Bash is an easy way to plug other code together, but it's
| terrible for math. Python is a much better way to plug
| other code together, and it's much better at math.
| RomanPushkin wrote:
| If you're learning Ruby, there is a free copy of my book
| available (CC BY 4.0 license):
|
| https://leanpub.com/rubyisforfun/ - English
|
| https://leanpub.com/rubyisforfun_ru/ - Po-russki
|
| (if you found typos, you can update the manuscipt
| https://github.com/ro31337/rubyisforfun)
| boberoni wrote:
| _> Unlike Python, in Ruby... There are a number of shortcuts
| that, although give you more to remember, you quickly learn. They
| tend to make Ruby fun and very productive._
|
| I use Python, but have never tried Ruby. The ecosystem for Python
| packaging is so chaotic that I've considered switching.
|
| Any Pythonistas/Rubyists here that could point out some Ruby
| shortcuts that make you more productive?
| batiste wrote:
| It really doesn't... After years using Ruby my mind never
| managed to parse its complicated grammar.
| DonHopkins wrote:
| Guido van Rossum put it this way:
|
| "Again, the templating language seems a weird mixture of HTML
| and Ruby, and I find Ruby's syntax grating (too many
| sigils)."
|
| https://www.artima.com/forums/flat.jsp?forum=106&thread=1461.
| ..
|
| >Then I decided to have a look at Ruby on Rails, just to see
| what I could learn from the competition. I watched two
| fascinating movies, but they went a bit too fast to really
| understand what was going on, and there seemed to be a fair
| amount of sleight of hand in the examples (a lot of default
| behavior that just happens to do the right thing for the
| chosen demo). Again, the templating language seems a weird
| mixture of HTML and Ruby, and I find Ruby's syntax grating
| (too many sigils). I believe I heard Greg Stein say recently
| that if you are really good in Ruby, CSS, HTML and SQL, you
| can produce great websites quickly with Rails -- but if you
| don't, you produce lousy websites quickly (just like with
| PHP).
|
| I quoted Guido's point about Ruby syntax 15 years ago in this
| lua-l discussion about Lua, Python, Lisp, and Ruby syntax,
| and the importance of not naming programming languages after
| naughty bits:
|
| https://lua-l.lua.narkive.com/Ly6vITFE/justify-
| introducing-l...
|
| >Stephen Kellett 15 years ago
|
| >[...] A little story to explain why in house languages are
| bad:
|
| >Years ago I worked for a company that had an in-house
| language (90-94) called Lull. [...]
|
| >(*) Come be real, who uses Lisp for commercial projects?
| Great language, but too many parens and no one uses it. Its
| the equivalent of Esperanto. So much promise, so little
| delivery. [...]
|
| >Don Hopkins 15 years ago
|
| >I read your message about "Lull" and a Dutch guy sitting
| behind me laughed out loud when I said the name of your
| language. (My dictionary says "lul" means "prick" or "cock"
| in slang, so it's a bit more explicit than "dick"!) This just
| goes to prove that how you name a language is important (but
| not as important as designing the language so it doesn't
| suck...)!
|
| >On the "too many parens" excuse for disliking Lisp: so why
| do you use XML and HTML? They have TWICE the number of
| parens, which are pointy instead of rounded, but lots of
| people seem to use them anyway. So "too many parens" is just
| a convenient and shallow excuse for disliking Lisp that
| avoids examining the real issue.
|
| >The real problem that many people have with Lisp is because
| it's perceived as a homosexual programming language, which
| causes unconscious cognitive dissonance, so people have to
| grasp for more socially acceptable reasons for disliking the
| language (like "too many parens"). Nobody wants to just say
| "I hate Lisp because it sounds gay", so instead they say "too
| many parens", even though most other languages suffer from
| too few parens, and are much less readable than Lisp because
| of their insane hierarchies of precedence rules. Programming
| tips 101: ALWAYS use parens even if you're sure the
| precedence rules will make your expression do what you want,
| because 1) other people need to be able to read the code and
| 2) you may be wrong. Drop any copy of K&R on the table so it
| lands on the spine and opens to a commonly used page, and I
| bet it opens on the table of precedence rules, because that's
| the page everyone always turns to. Lisp code never suffers
| from this problem.
|
| >The first thing most typical homophobic Americans think of
| when they hear the word Lisp is the gay stereotype of
| speaking with a lisp, so it unconsciously terrifies them. And
| the fact that "lambda" signifies unity under oppression, and
| is used as the gay/lesbian/bisexual/transgendered symbol only
| reinforces that impression:
| http://en.wikipedia.org/wiki/LGBT_symbol#Lambda ...And then
| there's the purple cover of Structure and Interpretation of
| Computer Programs, with the two gay dudes on the cover.
|
| >Anyway, millions of people program in Lisp every day with C
| syntax, but they just call it JavaScript, and suffer without
| macros, because of the inferior C syntax.
|
| >-Don
|
| >Fabien 15 years ago
|
| >@Don: your theory is fine for US people, but lack of love
| for Lisp is also observed in non-English speaking places. I
| learned quite recently that the word "lisp" also had another
| meaning than "nail clippings in oatmeal".
|
| >My guess would rather be that Lisp doesn't encourage common
| idioms and development approaches across people and teams,
| which makes it hard to:
|
| >- get into code you didn't develop
|
| >- work with more than a couple of teammates
|
| >- find a library that addresses your problem
|
| >- if you have several problems and find a lib to address
| each of them, get those libs to work together despite their
| incompatible macro hacks.
|
| >That, and Lisp took waaaay too long to acknowledge its
| platforms. It pretended to be OS independent, which meant
| many non-standard, non-compatible ways to interface with
| OSes, and therefore, plenty of platform issues as soon as you
| wanted to port or deploy a non-trivial solution. As written
| somewhere by Paul Graham, "Unix has won, get used to it".
|
| >Don Hopkins 15 years ago
|
| >Now that's some spot-on criticism of Lisp, much better than
| the "too many parenthesis" excuse that gets thrown around by
| linguistic homophobes suffering from cognitive dissonance.
|
| >I'm still waiting to hear somebody claim that they refuse to
| use XML and HTML because they have too many parenthesis
| (angled brackets). Or for somebody who hates Lisp's
| parenthesis but tolerates XML and HTML to explain why
| <foo>bar</foo> is easier to read than (foo bar).
|
| >Perl and C++ have way too much punctuation in general, and
| Ruby made a cargo cult design mistake in imitating Perl
| syntax. I agree with Guido van Rossum's comment on Ruby: "I
| find Ruby's syntax grating (too many sigils)". http://www.art
| ima.com/forums/flat.jsp?forum=106&thread=14614...
|
| >Wow, in what language does lisp mean nail clippings in
| oatmeal, and where can I get some of that stuff? It sounds
| delicious!
|
| >"Using these toolkits is like trying to make a bookshelf out
| of mashed potatoes." -- Jamie Zawinski, on X-Windows
| toolkits.
|
| >-Don
|
| [...]
|
| >Fabian: http://en.wikiquote.org/wiki/Larry_Wall look for
| "Lisp has all the visual appeal of oatmeal with fingernail
| clippings mixed in")
|
| [...]
| smitty1e wrote:
| The problem with lisp is `lack` of sigils to give one
| enough sense of flow.
|
| Moving the ( to the left of the function name somehow feels
| as disconcerting as gazing upon an non-trivial Haskell
| function and trying to map the type signature line to the
| function definition directly following.
|
| Confusion is the mother of "Back to python, where I can
| knock this out."
| DonHopkins wrote:
| To my eyes, sigils create turbulence, not flow. And they
| don't have obvious well defined standard meanings, and
| aren't self documenting or easy to look up in a manual or
| dictionary.
|
| Who can even remember how ASCII punctuation should be
| "alphabetized" in an index, let alone Unicode?
|
| However the pure parens of Lisp code look like concentric
| ripples on still water, instead of the raging rapids of
| pathologically punctuated Perl code.
|
| Jack Kerouac and William Shakespeare and Hunter S.
| Thompson all managed to write beautiful laminar flowing
| text with words, without resorting to sputtering splashes
| and eddies of excessive punctuation.
|
| https://www.quora.com/Who-are-some-writers-whose-texts-
| are-g...
|
| Would you really want to read and maintain somebody
| else's quirky code written in a programming language
| designed by e e cummings?
|
| The most difficult and important part of programming is
| choosing the right words and names, to help the reader
| understand your meaning and intention.
|
| But there are only a few punctuation characters, unless
| you resort to inscrutable C++ digraphs, trigraphs,
| unicode, ambiguous smilies ;), and emojis. (Is that
| punctuation after the smilie a drool, or an Oxford
| comma?)
|
| https://en.wikipedia.org/wiki/Digraphs_and_trigraphs
|
| Do you really believe peppering your code with
| punctuation and emojis instead of using meaningful
| evocative words makes it "flow" better?
|
| He was making an April Fools joke, but Bjorn Stroustrup's
| proposal for Generalizing Overloading for C++2000 would
| have actually improved the language's flow!
|
| https://www.stroustrup.com/whitespace98.pdf
|
| Edit:
|
| My friend and brilliant Lisp hacker Ken Kahn (who teaches
| kids AI programming with the Snap! visual programming
| language) was just inspired to explore these stylistic
| visualizations of Lisp programs with Dall-E:
|
| Ken Kahn:
|
| https://scholar.google.com/citations?user=9hQiyqcAAAAJ&hl
| =en
|
| Enabling children and beginning programmers to build AI
| programs:
|
| https://ecraft2learn.github.io/ai/
|
| A detailed painting of a Lisp computer program:
|
| https://drive.google.com/file/d/1pYPNlhD6Q4gvGpjy_SUcuthz
| 93i...
|
| A detailed painting of a Lisp computer program in the
| style of Ceezanne:
|
| https://drive.google.com/file/d/1SkWQmmpjOg_LhBW0xoEm_9Fs
| zXa...
|
| A detailed painting of a Lisp computer program in the
| style of Van Gogh:
|
| https://drive.google.com/file/d/16Mno-3mHUPPBmTaeM750SKLf
| 8hd...
|
| A detailed painting of a Lisp computer program in the
| style of Rembrandt:
|
| https://drive.google.com/file/d/1czti3cQzv6P0SCCjCzyRx-
| NHMlI...
|
| A detailed painting of a Lisp computer program in the
| style of Herman Brood:
|
| https://drive.google.com/file/d/1EORrmLdH6jY-
| ShjyzauTvXZ39kW...
|
| A detailed painting of a Lisp computer program in the
| style of Jackson Pollack:
|
| https://drive.google.com/file/d/1Oszo7fqugGTFjpALR1Y9v4AI
| Xwo...
|
| A detailed painting of a Lisp computer program in the
| style of El Greco:
|
| https://drive.google.com/file/d/1igFBKYAfGLBFxYPnNPp8UVbz
| yuA...
|
| A detailed painting of a Lisp computer program in the
| style of Matisse:
|
| https://drive.google.com/file/d/1-Q9jF0gbUXef86BiKEALf6Fe
| A4e...
|
| A detailed painting of a Lisp computer program in the
| style of Jan van Eyck:
|
| https://drive.google.com/file/d/1N5l3depTIAwP8dCscZ87_Hm9
| v5i...
| kazinator wrote:
| > _Who can even remember how ASCII punctuation should be
| "alphabetized" in an index, let alone Unicode?_
|
| Ideally, the entries should mostly be one character long,
| at most two, and appear i a dedicated non-alphanumeric
| index section that runs for no more than half a page.
| travbrack wrote:
| Any examples? I always found it easy to grok but I'm not at a
| very high level so I'm curious where it gets hairy.
| cycomachead wrote:
| There's a bunch of things to pay attention to in Ruby. I
| wouldn't say these get too hairy, but they trip students up
| for very understandable reasons.
|
| * `a ||= b` is not just `a = a || b`, but `a || a = b`
|
| * The distinction between defaults arguments and hash
| arguments in functional signatures has many edge cases --
| but it's much much better in Ruby 3.
|
| * There are still 2 pieces of syntax for hashes (`{a: 1}`
| and `{:a => 1}`) They are the same.
|
| * Curly bases show up a fair bit for a language that's not
| a braces language. :) They're in hashes, blocks, and %
| strings. e.g. `%w{a b c}` is the same as `%w|a b c|`.
| They're also used in string interpolation, e.g. `"Hello,
| #{name}"`.
|
| * There are sometimes many ways to do the same thing.
| There's Procs, blocks, and lambdas. % strings work with
| many characters.
|
| * `unless` for `if not...` and get wonky.
|
| * Overusing "surprise if" e.g. `do_thing if other_thing`
| can be hard to read.
|
| * It's so easy to monkey-patch and extend primitive
| classes, you might not realize when libraries do it.
|
| All of these are features that I actually find nice to use
| in the right contexts. But they can pop up when you don't
| expect, and they can definitely make Ruby a challenge to
| learn. That said with a little discipline (or just a linter
| ;)), I find a lot of Ruby code a joy to read and write.
| IshKebab wrote:
| > `do_thing if other_thing`
|
| Yeah I don't get why you would deliberately make the flow
| control confusing and backwards like that. Python list
| comprehensions are the same. They make the information
| flow backwards.
|
| This also has the effect of making nesting _really_
| confusing.
| greenpeas wrote:
| > > `do_thing if other_thing`
|
| > Yeah I don't get why you would deliberately make the
| flow control confusing and backwards like that.
|
| I like to use this as function guards, where the first
| lines in the body of a function can be:
| return xxx if some_edge_condition?
|
| example: https://github.com/rails/rails/blob/f95c0b7e96eb
| 36bc3efc0c5b...
| cycomachead wrote:
| Guard clauses are great, and when used appropriately
| clean things up. This is pretty much my only use of the
| pattern.
|
| (Ending boolean-returning methods with a ? is also a
| great convention in ruby.)
| bobbylarrybobby wrote:
| if some_edge_condition: return x
| msbarnett wrote:
| I've written both professionally and personally found
| Python makes it harder to see the early out, which makes
| it less valuable/explicit as a guard.
|
| The Ruby pattern is clear up front on what it _is_ rather
| than being a bag of conditions that you have to get to
| the end of to discover what they trigger.
| gls2ro wrote:
| For me this fits more into how I think or how I say
| things in my mind.
|
| It might be that I am not an english speaker, but for
| example when I say to someone a list of instructions I
| usually say it like this:
|
| "Add more water if the dough is dry"
|
| and I don't usually say
|
| "If the dough is dry add more water"
|
| The same for saying for example:
|
| "stop mixing if the dough is starting to tear"
|
| or
|
| "put the bread in the oven when it is ready"
| mypalmike wrote:
| It's even worse when you combine the two complaints:
|
| do_thing unless other_thing
|
| Which of course you find in many Ruby codebases.
|
| Python list comprehensions seem less painful to me
| because they read almost like the WHERE clause in SQL
| simple SELECTs. Definitely not the most straightforward
| thing one encounters in Python though.
| greenpeas wrote:
| I don't quite get the distinction in your first item:
| What's the difference between `a = (a || b)` and `a || (a
| = b)` ?
| Jabbles wrote:
| The rabbithole is here:
| https://stackoverflow.com/q/995593
| greenpeas wrote:
| wow, thanks. I worked with ruby for more than 5 years,
| and `||=` never surprised me.
|
| TLDR On the distinction between `a = (a || b)` and `a ||
| (a = b)`:
|
| * There is no difference when `a` and `b` are local
| variables (unless `a` is undefined, but that's an edge
| case)
|
| * The distinction manifests when `a=` is a method. (It
| could be a `[]=` or some attr_accessor). Then `a = (a ||
| b)` always invokes `a=`, whereas `a || (a = b)` only
| invokes `a=` when `a` is falsey.
|
| In essence however, `a ||= b` respects the intuitive
| definition that it sets `a` to `b` if and only if `a` is
| falsey.
| cycomachead wrote:
| Yeah, it's not usually an issue in practice. But I do see
| students get confused trying things out...and it's likely
| because learning in an interpreter doesn't often look
| like "real" code does.
| endorphine wrote:
| What does this mean, concretely speaking? Do you mean you
| can't remember the right syntax when trying to program in it?
|
| I know its syntax is complicated but I never felt this has
| caused me trouble. I guess writing a parser for it would be
| extremely hard, but that's another story.
| BiteCode_dev wrote:
| The optional parenthesis kills it for me. It makes scanning
| the code impossible: you have to understand each line
| context.
| endorphine wrote:
| How long do you program in Ruby?
|
| I understand this coming from a newcomer but after a
| while it felt like second-nature to me. I was curious
| about parent poster, because they said they are using
| Ruby for years.
| rubyist5eva wrote:
| How? I've been writing Ruby and Rails for over a decade
| and I can't really say it's ever been a problem for me.
| msbarnett wrote:
| How does this make it confusing? What information do you
| feel () gives you?
|
| You might say: foo().bar().baz()
|
| Ah well these are clearly method calls, they have ().
|
| But this is Ruby: foo.bar.baz
|
| These are clearly method calls too, because in Ruby
| _there's nothing else they could possibly be_. The ()s
| don't actually disambiguate anything. Unlike C or Java or
| some other languages with some notion of bare access to
| internal fields, there are always and only method calls.
| batiste wrote:
| Yeah, the optional parenthesis is one my biggest
| complaint with the language.
|
| It just makes things less readable, with not other
| benefits than making the code look more clever than it
| is.
| Hamuko wrote:
| You should probably try some 10-minute Ruby tutorial to see if
| the syntax doesn't completely scare you off.
| Gordonjcp wrote:
| When I looked at Ruby (admittedly a long time ago now)
| everything was 10 minute videos. Is there any actual useful
| material on it now?
| nomilk wrote:
| There's ~50 short exercises/lessons here:
| https://learnrubythehardway.org/book/
|
| I did them when I started out, and occasionally revisit as
| a refresher. It doesn't teach everything in ruby, but it
| absolutely gives enough to do just about anything you could
| want.
| regularfry wrote:
| The default guide for a long time was the Pickaxe book,
| which solidly pre-dates the availability of 10-minute
| videos by several years. There are a fair few links here
| that you might find useful: https://www.ruby-
| lang.org/en/documentation/
| AnthonBerg wrote:
| I like the RubyMine IDE a lot. The code intelligence is very
| good - it's so good that it tends to teach you Ruby as you use
| it. Code intelligence as in code navigation, easy access to
| documentation on the fly, refactoring, code style suggestions.
|
| The same goes for the tooling integration. It works with most
| of the development tools you'd use with Ruby and captures the
| integration pretty well in a UI and associated workflow.
|
| Link for your convenience: https://www.jetbrains.com/ruby/
|
| (No affilition except being a paying user.)
| gls2ro wrote:
| I am using both Vim and RubyMine and I strongly recommend
| RubyMine for anyone starting with Ruby.
|
| Having the possibility to have a Go to definition for almost
| any method is great and most of the gems have great code
| comments with a lot of nice examples.
|
| When I teach people to learn Ruby (I do this sometimes) among
| the first things I do is I explain to them how to open a gem,
| look at the source code, read it and then try to use it.
|
| I cannot thank enough the maintainers of the most popular
| gems for doing such a great job in having great ruby code and
| good in-file documentation.
| cycomachead wrote:
| More productive is really hard to say... But I personally
| prefer Ruby to Python. For smallish scripts, I really like
| Ruby's backticks for easily executing shell commands. And I
| find the metaprogramming support in Ruby great for some tasks.
| I'm not sure if that's what you're getting at.
|
| But especially with "modern" Python features like f-strings and
| the walrus operator there's not tons of differences that really
| stand out as "productivity".
|
| One thing to just remember: Ruby is not just the Ruby on Rails
| community. Rails is a dominate space, but it's not the only
| thing out there. At the same time, when it comes to scientific
| computing, ML, etc. the Python ecosystem is incredibly robust.
| There's plenty of awesome Ruby tools for these things too, but
| it is not the same.
|
| Ruby and Python are the two languages I primarily teach courses
| in, and used professionally. Ruby is my cup of tea personally,
| but they're both modern dynamic interpreted languages.
| ptx wrote:
| > _For smallish scripts, I really like Ruby 's backticks for
| easily executing shell commands._
|
| Executing external commands is pretty convenient in Python
| these days, now that we have subprocess.run [1], and passing
| the command as a list rather than through the shell seems a
| lot safer.
|
| Doesn't backticks open up the classic command injection
| issues (i.e. the same kind problem as SQL injection with non-
| parameterized queries) unless you're extremely careful to
| manually apply proper quoting in every single case?
|
| [1] https://docs.python.org/3/library/subprocess.html#subproc
| ess...
| noirbot wrote:
| It would, but most of the time when I'm using backticks,
| it's because I'm writing myself/my team a little helper
| script that will never get "injected" with anything.
| Backticks (and the other more featured ways of doing shell
| commands in ruby) make it really easy to write what amounts
| to a Bash script, but with a little more features and
| readability, or pull in some relevant libraries for some
| more complex task that would be annoying to do in pure
| Bash.
| ptx wrote:
| Your use case might be different from mine, but I find
| that usually there is some parameter needed for the
| command, usually a filename or sometimes the output from
| another command. Even if you're not accepting hostile
| data over the network, you probably want it to work
| correctly for any valid filename.
|
| With a bash script, or shell commands as strings in
| general, I can usually with some work be reasonably sure
| that I'm handling filenames with spaces correctly, so
| that it doesn't explode when it encounters something
| unusual... mostly, probably, in most places ... I hope.
| But what about filenames with newlines? Probably not as
| correctly. Etc.
|
| With a parameterized API, this all just works and is
| correct for all cases, so you don't have to think about
| arcane quoting rules.
| oezi wrote:
| I think with "shortcuts" they mean things such as $1 (first
| match group of a regex) or =~ (regex match operator).
|
| I general I rarely feel like I am unproductive in Ruby (or
| bogged down in boilerplate typing).
| cycomachead wrote:
| In that case -- I definitely agree Ruby usually gets out of
| way. It's often my go to for hacking on something, unless
| it's data science-y.
|
| I'll mention: implicit returns, return if, and safe
| navigation, the &. operator. Ruby's newer pattern matching
| features are really cool[1], especially for things like JSON
| structures, but I've only use started using them. Classes are
| also super easy to extend.
|
| Many of these things are also incredibly easy to abuse - but
| they have their places.
|
| [1]: https://docs.ruby-
| lang.org/en/3.0/syntax/pattern_matching_rd...
| transfire wrote:
| I'm not sure what "shortcuts" the author is referring, but
| perhaps... x = y || z # if y is falsy x = z
| x = f ? y : z # ternary operator %w{one two
| three} # array of words
|
| And so on.
| endorphine wrote:
| Also: x ||= 1 x &&= 1
|
| and the various built-in methods from Array, Hash,
| Enumerable, String etc.
| intuxikated wrote:
| These all exist in python, though you use or/and instead x =
| y or z x = f and y or z you can also use inline if/else x = y
| if f else z 3rd one just seems like an array of strings?
| ["One", "two", "three"] Not needing quotes for single words
| saves some typing tho.
| pmontra wrote:
| I loathe most shortcuts: too many things to remember and
| usually cryptic syntax. Maybe that's because I have to be a
| polyglot developer (Elixir, JavaScript, Ruby, Python) and I
| can't remember all the tiny details of each language.
|
| If you want to give a try to Ruby, get to understand blocks
| quickly. Instead of for item in list:
| work_on(item)
|
| which would work (with a closing end and no : ), the idiomatic
| way is list.each do |item|
| work_on(item) end
|
| or the one liner list.each {|item|
| work_on(item)}
|
| Check also map, select, each_with_index, each_with_object, etc.
| Blocks are fundamental to Ruby for reason that only practice
| can tell.
| jjgreen wrote:
| Since "work_on" takes a single argument which is a instance
| of Item, you'd be better off implementing it as an instance
| method, so item.work_on. Then you have the even more compact
| list.each(&:work_on)
| greenpeas wrote:
| Or with numbered parameters (since ruby 3.0)
| list.each { work_on(_1) }
| BiteCode_dev wrote:
| Swift has this as well, and it's really nice.
|
| Doing map(lambda x: x + 1, stuff) or [x + 1 for x in stuff]
| adds nothing of value for those very simple cases. I wish
| we had map($1 + 1, stuff), or ever better, stuff |> $1 + 1.
|
| Python does a lot of things right, but for a language with
| a strong emphasis on the iterator design pattern, I wish it
| would provide more expressive primitives.
|
| However, it comes with the FP territory, which Python is
| not well suited for, and it would also imply a higher cost
| of entry to beginners.
| kofejnik wrote:
| Quite horrible imo. Creeping closer and closer to Perl with
| each iteration
| pmontra wrote:
| Which is exactly the kind of shortcut I loathe.
| greenpeas wrote:
| you're not alone :) https://bugs.ruby-
| lang.org/issues/15723
|
| This syntax looks ugly, but it's really nice when writing
| short scripts. Combined with one line function
| declarations: `def foo(n)= bar`, it can make an irb
| session much faster/shorter.
| davidthewatson wrote:
| I've been using python for two decades and ruby exactly one
| decade ago for a couple years.
|
| Your comment on packaging is interesting.
|
| My perspective is that packaging on ruby was in nearly the same
| state ten years ago as python is now.
|
| My team switched ruby package managers several times during the
| ruby work and none of them ever worked reliably and was a
| regular root cause of fragility in our builds.
|
| I hope that ruby packaging has settled in that time while
| python has the same kind of cultural noise that afflicted ruby
| during that period. Popularity has downsides. Political
| packaging wars is one of them.
|
| I'm old school enough that I stick with tried and true pip,
| venv, and .env and its ilk.
|
| There was a long battle in downstream packaging for a while
| that I just didn't want to be involved in having seen the same
| thing in ruby.
|
| FWIW, if I were you I'd look at crystal, elixir, or nim. I was
| very productive in ruby but the near constant battle of
| wrestling with DSL's that are not concomitant with their parent
| is, IMHO, to be avoided. I've seen more than one team fall prey
| to that trap. Caveat emptor - pick your DSL's carefully.
| kawsper wrote:
| What do you mean by switching packaging managers? Ruby uses
| Rubygems and Bundler to manage packages.
|
| Are you referring to Ruby version managers that manages
| different versions of Ruby (rbenv, rvm, asdf, etc.)?
| ByteJockey wrote:
| They mention doing this a decade ago. They were probably
| using utilities to manage downloads from the ruby
| application archive (which would have still been around at
| the time) and automate running `setup.rb`
| davidthewatson wrote:
| Yes, all of the above. Sorry for the unclear language.
|
| At the time, I recall it being very distracting when the
| team was focused on shipping well-tested code. We had a
| world class devops guy, but we all ran into these build
| issues frequently enough that it was a regular complaint
| at retrospectives no matter what tooling we were using at
| the time or who was using it. It was not long after this
| that I read Daniel Greenfeld's book on Django that
| introduced the notion of "vanilla django" and that
| resonated with me, precisely because our rails tooling
| was decidedly not vanilla. My take now is that rails can
| have the same problems with regard to being "off the
| rails" WRT the aforementioned DSL's and such. I don't
| think the root cause is ruby as much as there are pockets
| of rails that are far from what DHH describes.
| nickjj wrote:
| > Any Pythonistas/Rubyists here that could point out some Ruby
| shortcuts that make you more productive?
|
| It depends on what you want to do.
|
| If it's building web apps there's Ruby on Rails, which is
| written in Ruby. In my opinion there's no alternative to this
| in Python. Sure there's Django but it's not the same even
| though both are considered batteries included web frameworks.
|
| One nice thing is you'll find both Python and Ruby SDKs for a
| ton of third party services (like Stripe, etc.). That goes a
| long ways for building things quickly and with confidence.
|
| Ruby's package manager is also a lot better IMO. It supports
| proper lock files out of the box and everyone uses gems with
| bundler. In Python it's a mix of pip, pipenv, poetry, etc. all
| of which have their own unique issues. With Ruby I never felt
| like I had to battle this aspect of the language. You just
| bundle install what you want and creating gems is the same
| process.
| lloeki wrote:
| If one wants to get into Ruby, please stay away from Rails as
| a first step into Ruby-land.
|
| Look into Rack and Sinatra first, _then_ Rails. Even if it 's
| a short trip it's going to be worth it.
| Lio wrote:
| This is personal opinion but these days I'd probably swap
| Sinatra for Roda[1] for small API services.
|
| It's generally faster, uses less memory and is a really
| good example of well written ruby code, IMHO. I also really
| like Jeremy Evans' book, Polished Ruby.
|
| 1. http://roda.jeremyevans.net/index.html 2.
| https://www.packtpub.com/product/polished-ruby-
| programming/9...
| MatthiasPortzel wrote:
| > Sure there's Django but it's not the same
|
| Could you elaborate on this? I've used both Django and Rails
| and in my mind they're direct parallels to each other. For
| example: in Rails you write migrations and then it generates
| a schema.rb, and in Django you update your model schema and
| then it generates migrations.
|
| They have very different philosophies, sure (reading the
| Rails manifesto made that clear), but from a technical
| standpoint they have pretty good feature parity.
| likortera wrote:
| I think you're only considering the backend part of these
| frameworks.
|
| Rails is really full stack. Django's frontend story is a
| joke.
| [deleted]
| shaicoleman wrote:
| There are thousands of little things that make Ruby nice. They
| all add up to a more enjoyable experience. I'll give you one
| tiny example:
|
| Python: from datetime import date if
| date.today().weekday() == 5: print("It's Saturday")
|
| Ruby: require 'date' puts "It's
| Saturday" if Date.today.saturday?
| AnonymousPlanet wrote:
| How do you know which 'Date' your are using. How do you know
| it's the one from 'date'?
|
| That's like using * imports in Python which is a huge pain
| once you done even minor refactoring.
| shaicoleman wrote:
| > How do you know which 'Date' your are using. How do you
| know it's the one from 'date'?
|
| Ruby allows you to check where a method is defined, e.g.:
| puts Date.singleton_method(:today).source_location
|
| Although in this case it returns nil because it's
| implemented in C. But it would return the location if you
| overrode it.
|
| There are various tools to see what the code is doing:
| invoking a debugger and stepping into the code, tracing the
| code execution via TracePoint, etc.
|
| The Zeitwerk autoloader which comes with Rails enforces
| that the class name matches the filename.
|
| Naming conventions, specs, a quick grep and avoiding
| generic names make it almost a non-issue in my experience -
| only happens every few years or so, and usually quite easy
| to fix.
|
| Ruby gives you a lot of power, but it doesn't stop you from
| shooting yourself in the foot.
|
| https://m.signalvnoise.com/provide-sharp-knives/
| gedy wrote:
| Yeah in the Rails shops I've worked with, this "developer
| productivity" turns into a nightmare with large codebases.
| ouija wrote:
| I prefer the Python code here. The import is explicit, so if
| you want to know where "date" comes from, that's easy. In a
| modern IDE I don't write imports manually anyway.
|
| You could write it as a one-liner in Python as well, but I
| would prefer not to. print("It's Saturday")
| if date.today().weekday() == 5 else None
|
| That the Python library doesn't define constants for days is
| unfortunate, but not a limitation of the language.
| by_the_bay wrote:
| Agreed, in complicated Ruby packages with layers and layers
| of dependencies it quickly becomes a nightmare to identify
| which class comes from which import, where it's defined,
| etc. Never an issue in python
| shaky-carrousel wrote:
| The ruby oneliner looks way cleaner and more natural than
| the python one.
| rcfox wrote:
| Would you ever use either in a real codebase though?
| xipho wrote:
| As opposed to a fake codebase? This sounds a bit like
| https://en.wikipedia.org/wiki/No_true_Scotsman.
| mod wrote:
| No, not as opposed to a fake codebase. I think it's clear
| what they meant.
|
| One incredibly common alternative to a codebase is a
| script.
| xipho wrote:
| Ok, I'll bite. I don't, I think it was a knee-jerk
| reaction post that didn't think things through for more
| than a couple seconds. I'm guilty of many of these, it's
| not the end of the world.
|
| I know many "scripts" that have far more curation,
| history, and accumulated effort than any "codebase" sensu
| your post, I don't think this has any relevance to his
| question. Use is use. "Real" or "Fake" in terms of a
| standard library like "date" (see my other post) just
| isn't a useful dichotomy IMO.
| orf wrote:
| As opposed to either a snippet in a REPL or a comment on
| hacker news.
| xipho wrote:
| The code is part of a standard, used-almost-everywhere
| library, `date`. Code in these libraries, from what I
| undersand, have a ton of thought behind them. It might
| follow that there were good real-life use-cases ready to
| use the code that influenced its presence in that
| library?
|
| Also: https://github.com/search?l=Ruby&q=Date.today.satur
| day%3F&ty...
| orf wrote:
| So the answer to the original question was simply "yes".
| shaky-carrousel wrote:
| Well, yes. In fact it's the recommended style for simple
| conditions.
| cutler wrote:
| The else None is redundant, though. If you want a one-liner
| in Python just ignore the indentation: if
| date.today().weekday() == 5: print("It's Saturday")
| dragonwriter wrote:
| Preferring the Python import syntax doesn't preclude
| preferring the Ruby library design.
| petepete wrote:
| Why do I need to remember that Saturday is 5?
| d0mine wrote:
| >>> import calendar >>> calendar.SATURDAY
| 5
| petepete wrote:
| Yeah, I'll take `Date#saturday?` thanks.
| squeaky-clean wrote:
| ?Por que necesito recordar que el sabado es "Saturday"?
| unixhero wrote:
| Porque en ese caso no usas un IDE moderno.
| throwawaymaths wrote:
| Tampoco "if", "for", "while"...
| wiseowise wrote:
| Rest of the language doesn't bother you?
| quickthrower2 wrote:
| You are allowed to define your own constants.
| greenpeas wrote:
| S looks like 5 if you squint. not hard to remember
| jjgreen wrote:
| So Sunday?
| greenpeas wrote:
| No! Sunday is 6 because "Sunday" has 6 letters.
| jjgreen wrote:
| That's it, I'm switching to Python!
| tzs wrote:
| I think every language I've used has annoyed me in how it
| handles dates and times.
|
| I've been tempted several times to sit down and repeatedly
| read Dershowitz and Reingold's book "Calendrical
| Calculations" [1] cover to cover until I thoroughly
| understand it, and then write my own date and time library
| and port it to every language I use.
|
| That would mean that when I learn a new language I'd have to
| take some time to port my date and time library, but looking
| at the languages I already know that would have been less
| than the time it took me to find and learn to deal with the
| quirks and annoyances in their libraries. I see no reason to
| believe that this will be different for any future languages
| I decide to learn.
|
| Yes, I know this would be annoying to whoever has to take
| over my code when I'm gone, but I tend to stick around on
| projects until they reach end of life and so there almost
| never is anyone that comes after me.
|
| [1] https://www.amazon.com/Calendrical-Calculations-Ultimate-
| Edw...
| scubbo wrote:
| I cordially invite you to look into the clusterfuck that is
| Go's treatment of date formatting. Everything else will
| seem clean and logical by comparison.
|
| Per https://golang.cafe/blog/golang-time-format-
| example.html:
|
| > Format returns a textual representation of the time value
| formatted according to layout, which defines the format by
| showing how the reference time, defined to be Mon Jan 2
| 15:04:05 -0700 MST 2006 would be displayed if it were the
| value; it serves as an example of the desired output. The
| same display rules will then be applied to the time value.
|
| So, for instance, if you want to format a date in ISO
| format (YYYT-MM-DDTHH:mm:ss), you have to figure out how
| the reference date would be displayed in that format
| ("2006-01-02T15:04:05"), and pass that as the format
| string.
| DangitBobby wrote:
| I agree, of all the date formatting I've encountered,
| Go's is the worst.
| dragonwriter wrote:
| If I didn't know that was actually an accurate
| description of Go date formatting, I'd think it was
| satirical.
| politelemon wrote:
| If I only used Ruby I'd probably prefer the Ruby example. As
| someone who jumps across many languages, I prefer the first.
| I found Ruby's approach to things was at many times too
| clever, to the point of becoming unreadable and cryptic.
| Python prefers clearness over cleverness.
| heartbreak wrote:
| How is computing a weekday where the caller (and reader)
| must know that Monday=0 not cryptic?
| remram wrote:
| Especially when other systems like cron have used
| Monday=1 forever
| throwawaymaths wrote:
| I think the if being an infix operator is a bit
| "cryptic". I mean IMO it is _easier to read_ - and in
| reality it 's not a problem, because it's pretty
| unambiguous what's going on, but some people get annoyed
| by "oh you can do that in ruby?" Trigger that happens the
| first few times you see it.
|
| Probably same with fields/methods with a postfix ?
| dragonwriter wrote:
| > Probably same with fields/methods with a postfix ?
|
| It's not a "postfix ?", it's literally just "?" being
| part of the identifier name. (It's convention for methods
| that are boolean predicates.)
|
| Also, Ruby doesn't have fields. (It has instance
| variables, but they don't have dotted access, so they
| aren't in the same namespace as methods of the same
| object the way fields are.)
| mod wrote:
| I agree that's a little weird, but for me the consequence
| of it is small.
|
| I'm going to catch that bug quickly.
|
| When Ruby does a magic import, that would sometimes cost
| me a lot of time tracking it down when I first started
| with Ruby. I don't remember it being a big deal anymore
| after a couple of years.
|
| (I like both languages)
| BiteCode_dev wrote:
| I can't fathom optional parenthesis. In this code it makes it
| very hard to know if today is an attribute or a method
| without knowing the context, meaning I can't scan the code, I
| have to read it carefully.
| jenrzzz wrote:
| It's always a method. Ruby doesn't expose instance
| variables unless you define accessor methods for them.
| [deleted]
| fny wrote:
| I'm going to emphasize this as well. Everything is an
| object, and everything called on an object is a method.
| Full stop.
|
| Unlike with other languages, there is no ambiguity here.
|
| In python, you don't know when you dir() an object
| whether your dealing with a property or method. In Ruby,
| you are guaranteed it's always a method. A perk is that
| you don't need parens.
| ek750 wrote:
| Exactly. Once you get some basics of Ruby, there is no
| ambiguity, and I find it quite elegant.
|
| And I think I'm in the minority here, but I prefer the
| cleanliness of optional punctuation.
|
| That feature also allows for fluent DSLs (which seem to
| be falling out of favor for various reasons), but is one
| of the reasons I still love Ruby.
|
| To look at the other side, I hate having to constantly
| add semicolons and parens in other languages. Makes my
| poor fingers hurt even more than they usually do.
| by_the_bay wrote:
| Makes reading ruby so much more difficult. Also optional
| return statements. If you need to refactor a function, it's
| not always obvious that it's relying on an implicit return
| and super easy to break things IMO
| gls2ro wrote:
| (not trying to convince you as I think in this thread no
| one will be convinced of anything)
|
| Knowing that in Ruby a method will always return its last
| executed line unless explicitly returned early makes (at
| least for me) things very easy to get.
|
| A method with two branches will always return the last
| line of the executed branch, thus you will always know
| what the response could be.
|
| But this (IMO) is because Ruby OOP where the main concept
| is that when you are invoking a method you are actually
| sending a message to that object thus you should get a
| response. So Ruby makes this way of working with objects
| universal.
|
| Once you call a method you will get a response.
|
| I find it strange the other way around, working in
| languages where I need to put return even on the last
| line of the method. For example after almost one year of
| full time backend development in Ruby, I needed to write
| some JS code. I debugged for half an hour why a short
| function that I wrote was not working properly until I
| got it: I need to add 'return' to that last line to get
| the actual result. This was strange for me :)
| nickjj wrote:
| > I can't fathom optional parenthesis.
|
| I think this kind of falls in line with the idea of Ruby
| giving you sharp knives[0].
|
| Like you I used to have a love / hate relationship with
| this because it feels inconsistent to sometimes use
| parenthesis and sometimes not. In a world where you just
| want to run Python's Black code formatter and always use
| parenthesis, having to think about when to use parenthesis
| feels really tedious.
|
| But I think nowadays I'm happy that they are optional
| because when you want them to be optional it creates a
| really nice aesthetic to your code.
|
| For example with Rails you can do: `2.days.ago` and then
| there's also things that feel like a mini DSL such as
| `validates :title, :body` or `belongs_to :users`. These
| just look nicer without parenthesis.
|
| With that said, I do use parenthesis more often than not
| but it's nice to avoid using them when it makes something
| look nicer visually.
|
| [0]: https://rubyonrails.org/doctrine#provide-sharp-knives
| sampo wrote:
| > I can't fathom optional parenthesis.
|
| How about optional dots in Scala? if (Day
| today saturday) println("It's Saturday")
| disgruntledphd2 wrote:
| Those are worse, but yeah, same principle.
| dragonwriter wrote:
| > I can't fathom optional parenthesis. In this code it
| makes it very hard to know if today is an attribute or a
| method without knowing the context.
|
| Optional parentheses exist because it is impossible for
| there to be ambiguity: after a dot, if a name starts with a
| lowercase letter it is a method (and the reference is a
| call). If it starts with an upper case letter, it is
| constant (which is not callable as a method.) There are no
| other possibilities.
|
| "Attributes" in Ruby are literally just getter methods
| (possibly paired with setter methods.) There is no object-
| dot-field access to fields (instance variables exist, but
| outside access to them doesn't use that syntax, but instead
| goes through a different set of method calls:
| Object#instance_variable-(get/set)
| z9znz wrote:
| There may be other things about Ruby that I disagree with,
| but this is probably my primary disagreement.
|
| It does make code more difficult to understand for exactly
| the reason you mentioned, and furthermore it can sometimes
| be disallowed based on the rest of the expression (such
| that parens are required).
|
| In my own Ruby code, I often use parens when they are
| optional.
| ByteJockey wrote:
| Given the context of this thread (comparison of ruby and
| python), it should be noted that python also has this. You
| can decorate a method with `@property` and call the method
| without parentheses.
|
| It's really nice because it means you don't have to pre-
| wrap all of your properties with accessor methods. They can
| just be properties, and if something changes, you swap the
| property out with a decorated method and you don't need to
| change any code.
| MatthiasPortzel wrote:
| I started writing ruby a couple weeks ago, and it threw me
| off at first. But you get used to it very quickly.
| gls2ro wrote:
| In case you want (and need) to get how to think in Ruby I
| recommend you to listen to this talk by Sandi Metz (and
| in general I recommend all her talks even if they are
| old): https://www.youtube.com/watch?v=XXi_FBrZQiU
|
| It presents OOP in Ruby in such a beautiful way and it
| takes a while to start thinking like this.
| bsaul wrote:
| From what i've seen ruby is definitely on the downward slope
| regarding adoption and python has become a defacto standard in
| some fields. Its ecosystem is much better in pretty much every
| domain, so i don't think there's any point switching at the
| moment, honestly.
| jillesvangurp wrote:
| I've used both. I slightly prefer python over ruby. But I
| haven't used either recently.
|
| Ruby's strength is internal DSLs. Python's strength is that
| it's simple to pick up for people. There's a large community
| of people that are not primarily programmers that use it. The
| reason for this is that it is a very easy language to get
| started with.
|
| Both share the same problem: they are weakly typed scripting
| languages. Both have in common that type annotations have
| been retrofitted to the language. But it's an uncomfortable
| and awkward retrofit in both cases and their respective
| communities seem to regard using types as an optional and
| inconvenient thing. Ruby with types of course exists. E.g.
| Crystal is nice apparently. But I've not really seen that
| used in the wild.
|
| Python is enormously popular; ruby's popularity seems to have
| declined a lot. I know a lot of former Ruby programmers that
| have moved to different languages and only a handful that
| still use it. It's not an obvious language to pick up for
| younger programmers. There are so many other languages to
| choose instead.
|
| IMHO the key innovation in language design in recent years
| has been type inference. This has lead to a new breed of
| languages that keep most of what made python and ruby
| popular: the ability to write code with a minimum of
| verbosity but without sacrificing type safety. Whether you
| use Kotlin, Typescript, C#, or even Java: they have type
| inference now and it reduces the verbosity that comes with
| having types. Scripting vs. compiled languages is much
| murkier these days where scripting languages have compilers
| or transpilers and linters and compiled languages have REPLs
| and all languages can now run in a browser via WASM anyway.
| The distinction is just not that relevant anymore.
|
| I write a lot of Kotlin, have dabbled a bit with typescript
| and I don't think I'll ever use languages without proper
| types again. Just not worth it for me. I don't see the value
| of not having a good typing system. Kotlin is interesting to
| me because internal DSLs are a thing with it; just like they
| were a thing with Ruby. And it can use javascript as a
| compilation target. Ruby has a slightly nicer syntax for DSLs
| than Kotlin for internal DSLs. But I don't mind curly braces
| and having strong typing enables a lot of good stuff. Like
| proper IDEs with refactoring, autocompletion, auto-fixes,
| etc. which are all very nice things to have in a DSL.
|
| I use Kotlin DSLs for writing CSS, HTML components (we use
| kotlin-js), writing elasticsearch queries (I maintain the
| multi-platform kt-search library), gradle build files (which
| uses kotlin script), and quite a few more things. IMHO, it
| could do a lot of things that python is popular for as well.
| cutler wrote:
| C# and Java with minimum verbosity? That I'd like to see.
| Kotlin.js HTML generation is just hideous.
| pmontra wrote:
| > they are weakly typed
|
| I think you should check the difference between strongly
| and weakly typed languages [1]
|
| You probably intended dynamically typed.
|
| [1] https://en.wikipedia.org/wiki/Strong_and_weak_typing
| n0tth3dro1ds wrote:
| funnybookbinder wrote:
| The parentheses become less obtrusive when you indent
| lisp code properly. Then you just read it according to
| indentation like Python. I don't find the parentheses
| problematic.
| keithalewis wrote:
| Good thinking. You might have to learn something new.
| z9znz wrote:
| Here's a rough list of benefits of Ruby compared to Python.
| It's not well organized and the examples are difficult to show
| in a comment box, but I have pages of notes of why Python is
| frankly a horrible language compared to Ruby.
|
| Every expression returns a value, so you can assign the result
| of an if/else or switch statement to a variable. Within your
| conditional clauses, you don't have to repeat assignments or
| return values. If the logic goes down that branch, then the
| last value in that block is the return value.
|
| This also means you don't have to have explicit 'return'
| statements in functions. Whatever the last value of the last
| expression is, that's your function return value. You can use
| an explicit return if you want to exit the function early,
| however.
|
| Ruby has a switch (case/when) statement. Python finally has
| this in 3.11 I believe, but it took forever to get.
|
| Hash.dig(). If you have nested hashes (dicts), you can
| myhash.dig(:top_key, :lower_key, :even_lower_key)
|
| In objects, you can control which attributes can be
| read/written via attr_reader, attr_writer, attr_accessor. So
| you can make an attribute have a default getter if you use
| attr_reader :some_attribute, and then you can write your own
| setter if you want to control how it gets assigned to. You can
| even simply not have a setter, so you can effectively make an
| attribute read-only.
|
| Clean, simple hash initializers: h = Hash.new { |h, k| h[k] = {
| age: 0, nickname: k } }. So now you can just start assigning to
| values in h like h["bob"][:attr1] = 28, and now h["bob"] refers
| to a hash with age 28 and nickname "bob". Yes Python has
| defaultdict, but it's an extra thing you have to use, and it's
| clumsy compared to the Ruby approach.
|
| Hash (dict) merging: It's a mess in Python. In ruby it's just
| h1.merge(h2), or even h1.merge(key_to_update: 123). And you get
| a new hash as the result. Or you can merge in place with
| merge!(), changing the original.
|
| Function names with ! and ? greatly simplify function naming
| (and improve readability). So instead of is_foo(), you just
| have foo?(). And if you want to indicate that you are doing
| something destructive, you name it foo!(). This is a common
| pattern in Ruby libraries, and you often have functions which
| return a new value and functions with the same name followed by
| ! which modify the input value. String.strip() returns a new
| string without leading/trailing whitespace, while strip!()
| modifies the input string to the same effect.
|
| Python's list comprehensions are arguably ugly and messy and
| harder to visually parse when reading. Ruby has consistent ways
| of doing operations on collections. This would take a full page
| to show examples.
|
| Copying and pasting code in Python often results in new code
| which is indented wrong (in the wrong scope), and which you
| must manually fix. This is not a problem in Ruby, since there
| are actual 'end' statements. Editors know how to properly
| indent what you paste.
|
| Safe navigation. myobj&.someattr&.foo will give you the value
| of foo or nil if myobj or someattr don't exist. You have to use
| ifs to do this in Python.
|
| Array flattening. nested_arrays.flatten(). But in python, you
| have to use something like list(itertools.chain(*arr)), but
| that fails if the first element of the list is an int (not an
| iterable).
|
| Gettings hash/dict keys. In Ruby, you just do myhash.keys and
| you're done. But in Python there are several ways to get the
| keys, none of which is as simple and obvious as just keys().
|
| Not allowing typos to silently fail. With Python, you can take
| an object and assign a value to a non-existent attribute. You
| might do this accidentally if you have a typo when trying to
| set an actual attribute: myobj.first_Name = "bob". Python will
| happily do that, and you'll later debug and wonder why
| myobj.first_name == "" (and then notice that you have this
| similarly named attribute now called first_Name). Duh. I guess
| you could say it's convenient to be able to do this, but it's
| more a footgun. Ruby will bark at you if you try this.
|
| List sorting in Python is in-place, so you can't non-
| destructively sort and get the sorted list returned. In Ruby
| you have a choice. sort() is non destructive, and sort!() is
| in-place.
|
| I've got more, but this is enough.
| maligree wrote:
| Using the sorted() built-in returns a new sorted array.
| Getting keys from a dictionary is literally just calling
| dict.keys(). Sorry, but I don't think you've used Python
| enough to offer lists like these.
| z9znz wrote:
| I stand corrected on the mylist.sort() vs sorted(mylist).
| But really, such a mistake is more likely with two very
| different ways of doing the same kind of operation.
|
| In ruby you would just mylist.sort() for a new sorted list
| (although parens are optional if no arguments, but I show
| them), or mylist.sort!() to sort mylist in place. You don't
| have to know two very different things. Plus it's obvious
| with the !
|
| > Getting keys from a dictionary is literally just calling
| dict.keys()
|
| Nope. Unless your definition of "keys" is a 'dict_keys'
| class. Chances are really good that what you wanted was a
| list of keys, not some object which does not behave exactly
| like a list. If you want to access the keys by index, you
| can't do it like mydict.keys()[0] because dict_keys does
| not have an index method.
|
| Oddly, if you want a list of keys of a dict in Python, you
| just do list(mydict).
|
| But you can also do [*mydict], which gives you a list of
| keys but is something special you have to learn.
|
| Here's a fun one. Give me the first key of a dict.
|
| Ruby: mydict.keys.first
|
| Python: (several ways)
|
| next(iter(mydict)) # which makes no sense at all... asking
| for the next value of something when you're actually asking
| for the first.
|
| list(mydict)[0]
|
| [*mydict][0]
|
| What if you want the values of the dict? Well, no surprise,
| Python gives you a dict_values object when you do
| mydict.values(). Likewise, you can't do listy things with
| that because it's not a list. You have to convert it to a
| list with list(mydict.values()). Or you can do the
| [*mydict.values()] thing.
|
| Python is full of so many inconsistencies, the cognitive
| overhead is much higher than it needs to be. I would argue
| that it makes people dumber, because they have to waste
| mental energy learning weird things for special cases.
|
| But what about the rest of my previous post list?
|
| Here's one I left out. The return-early pattern is common
| in imperative programming. We like to exit a function as
| soon as we know things aren't going a certain way.
|
| In Ruby: x = fetch_object("bob") or return "bob not found"
|
| In Python you need 2 or 3 lines (2 if you're using the
| walrus := operator).
|
| if (x := fetch_object("bob") is None):
| return "bob not found"
|
| How about setting a value for a variable if it is unset?
| This is a common thing done when you have variable
| arguments
|
| Ruby: x ||= "default"
|
| Python: x = x or "default" # not only does it look stupid
| setting a thing to itself, but it will fail if x is zero.
|
| Edit: fixed asterisks.
___________________________________________________________________
(page generated 2022-07-16 23:02 UTC)