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?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?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. >>> import calendar
>>> calendar.SATURDAY
5Also: https://github.com/search?l=Ruby&q=Date.today.saturday%3F&ty...
One incredibly common alternative to a codebase is a script.
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.
I just interpreted their post as talking about bigger, organized projects, instead of small scripts.
I personally draw a distinction between "codebases" and most everything else. One of the key differences is "would I start a new git repo?"
"Real projects" get a repo for sure.
It's not too diminish smaller projects. Almost all of the most useful things I've ever built were very small. But when you can grok the whole script, and you're likely to be the only user..."codebase" isn't the word I'd bust out.
I'm sure you can think of many exceptions to this. Thinking of exceptions is a good quality for programmers.
I don't think the word "real" (codebase) was a very important modifier.
if date.today().weekday() == 5: print("It's Saturday")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)
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.)
I'm aware ruby doesn't have fields, I called it fields/methods because it's a method in ruby but people in other languages will read it as a field, which it is, a good percentage of the time.
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...
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.
package main
import "fmt"
import "time"
func main() {
three_secs, _ := time.ParseDuration("3s")
five := 5
fmt.Println(five * three_secs) // error: type mismatch
fmt.Println(three_secs * three_secs) // 2500000h0m0s
}EDIT: Wait, I don't even understand how that can work, even in a broken way. Since I guessed 25000006060=9,000,000,000, I guessed that a "second duration" is really just a wrapper around `3,000` (ms) or `3,000,000` (ns) - but neither of those square to 9E9. In fact, the square root of 9E9 is a distinctly non-round number. What's going on here?
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.
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.
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.
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.
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)
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 :)
How about optional dots in Scala?
if (Day today saturday) println("It's Saturday")It presents OOP in Ruby in such a beautiful way and it takes a while to start thinking like this.
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.
That's like using * imports in Python which is a huge pain once you done even minor refactoring.
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.