[yast-devel] Welcome to the Wonderful World of Ruby
[shundhammer @ morgul] ~/tmp % cat weird.rb #!/usr/bin/ruby class Weird attr_accessor :foo def initialize @foo = "foo" end def doit1 puts "doit1" puts foo + "bar" end def doit2 puts "doit2" puts foo +"bar" end end weird = Weird.new weird.doit1 weird.doit2 [shundhammer @ morgul] ~/tmp % ./weird.rb doit1 foobar doit2 Traceback (most recent call last): 1: from ./weird.rb:23:in `<main>' ./weird.rb:17:in `doit2': wrong number of arguments (given 1, expected 0) (ArgumentError) What's going on here? Why does it crash? What's the difference between "doit1" and "doit2"? (Spoiler alert: solution after the blank lines) Yes, it's just that one blank after the plus operator, and it makes all the difference. It turns out that some time ago (with Ruby 2.3), the Ruby string class got a brand new unary plus operator (which is what we had all been missing for so long, of course). That unary plus calls String.unfreeze on that string. And in Ruby, the parentheses for a function call are optional. This is an accident waiting to happen, and it happened right here: Ruby interpreted this as a function call because the plus can be interpreted as an unary plus here, so it decided to unfreeze the constant "bar" string and pass it as an argument to the foo() method - which exists; it is the getter to the @foo member variable (implicitly created by attr_accessor: foo). Of course, this getter does not accept any parameter, so it complains. Actually it's pure luck that it does not accept a parameter and complains instead; if it had been a function that can accept a parameter, it would have happily called it with the unfrozen "bar" string and just done random garbage with that unintended parameter. ARGH. This is when "meaning good" (as in "the opposite of doing good") meets duck typing and happily executing any random garbage. If I really want to unfreeze a frozen string, I will happily tell Ruby to do just that. But no, there was a chance to make a cryptic scripting language even more cryptic by introducing stuff like an unary plus operator for strings, of all things. Tricky programming is soooo cool. Readable and maintainable code is sooo overrated. ARGH. Kind regards -- Stefan Hundhammer <shundhammer@suse.de> YaST Developer SUSE Linux GmbH GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg) Maxfeldstr. 5, 90409 Nürnberg, Germany -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 12/12/18 5:40 PM, Stefan Hundhammer wrote:
[...]
Tricky programming is soooo cool. Readable and maintainable code is sooo overrated.
Just to get you even on worse mood. ;-) https://www.destroyallsoftware.com/talks/wat -- Ancor González Sosa YaST Team at SUSE Linux GmbH -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 13.12.18 11:02, Ancor Gonzalez Sosa wrote:
Just to get you even on worse mood.;-)
Yes, I've seen that before some time ago; that's a really good collection. ;-) It makes one reconsider career choices, though. Maybe software engineering wasn't such a bright idea; becoming a baker gets increasingly attractive. If only it wasn't for the crazy work hours... ;-) CU -- Stefan Hundhammer <shundhammer@suse.de> YaST Developer SUSE Linux GmbH GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg) Maxfeldstr. 5, 90409 Nürnberg, Germany -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
V Wed, 12 Dec 2018 17:40:15 +0100 Stefan Hundhammer <shundhammer@suse.de> napsáno:
[shundhammer @ morgul] ~/tmp % cat weird.rb #!/usr/bin/ruby
class Weird attr_accessor :foo
def initialize @foo = "foo" end
def doit1 puts "doit1" puts foo + "bar" end
def doit2 puts "doit2" puts foo +"bar" end end
weird = Weird.new weird.doit1 weird.doit2
[shundhammer @ morgul] ~/tmp % ./weird.rb doit1 foobar doit2 Traceback (most recent call last): 1: from ./weird.rb:23:in `<main>' ./weird.rb:17:in `doit2': wrong number of arguments (given 1, expected 0) (ArgumentError)
Well, at least ruby syntax check returns you warning (and of course rubocop also). Maybe we can simply check for warning in this check in travis? As we already did syntax check, but it is not hard failure because meta programming can potentially allows you to survive this situation. try it yourself: ruby -wc weird.rb # w is warning and c is syntax check /tmp/weird.rb:17: warning: ambiguous first argument; put parentheses or a space even after `+' operator Syntax OK Josef
What's going on here? Why does it crash? What's the difference between "doit1" and "doit2"?
(Spoiler alert: solution after the blank lines)
Yes, it's just that one blank after the plus operator, and it makes all the difference.
It turns out that some time ago (with Ruby 2.3), the Ruby string class got a brand new unary plus operator (which is what we had all been missing for so long, of course). That unary plus calls String.unfreeze on that string.
And in Ruby, the parentheses for a function call are optional.
This is an accident waiting to happen, and it happened right here: Ruby interpreted this as a function call because the plus can be interpreted as an unary plus here, so it decided to unfreeze the constant "bar" string and pass it as an argument to the foo() method - which exists; it is the getter to the @foo member variable (implicitly created by attr_accessor: foo). Of course, this getter does not accept any parameter, so it complains.
Actually it's pure luck that it does not accept a parameter and complains instead; if it had been a function that can accept a parameter, it would have happily called it with the unfrozen "bar" string and just done random garbage with that unintended parameter.
ARGH.
This is when "meaning good" (as in "the opposite of doing good") meets duck typing and happily executing any random garbage.
If I really want to unfreeze a frozen string, I will happily tell Ruby to do just that. But no, there was a chance to make a cryptic scripting language even more cryptic by introducing stuff like an unary plus operator for strings, of all things.
Tricky programming is soooo cool. Readable and maintainable code is sooo overrated.
ARGH.
Kind regards
-- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 13.12.18 11:12, Josef Reidinger wrote:
Well, at least ruby syntax check returns you warning (and of course rubocop also). Maybe we can simply check for warning in this check in travis? As we already did syntax check, but it is not hard failure because meta programming can potentially allows you to survive this situation.
try it yourself:
ruby -wc weird.rb # w is warning and c is syntax check
/tmp/weird.rb:17: warning: ambiguous first argument; put parentheses or a space even after `+' operator Syntax OK
Yes. That warning is COMPLETELY USELESS. It does not answer any question, it just raises questions. In that regard, Ruby is even worse than gcc was 15 years ago. The gcc people at least in the course of those decades managed to issue well understandable error messages. So we'll only have to wait for another 15 years or so for Ruby to catch up. Well - wait; Ruby is indeed not that new: https://en.wikipedia.org/wiki/Ruby_(programming_language) "First appeared: 1995; 23 years ago" One would think that this is plenty of time to come up with some rudimentary sanity checks and error messages that can be understood by the average developer. So, please, let's not make any more excuses for something that appears to be fundamentally broken. It's the mindset of those people that makes it worse, and the tendency to find apologies for something that is clearly broken is part of it. Kind regards -- Stefan Hundhammer <shundhammer@suse.de> YaST Developer SUSE Linux GmbH GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg) Maxfeldstr. 5, 90409 Nürnberg, Germany -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
Dne 12. 12. 18 v 17:40 Stefan Hundhammer napsal(a):
[shundhammer @ morgul] ~/tmp % cat weird.rb #!/usr/bin/ruby
I'm sorry but I have somehow missed the point of this e-mail. A. If it's a "learning opportunity", then I'm missing the happy-end B. If it's for Ruby surrender, then it's, I'm afraid, useless C. If it's a "sigh" one, then ... ? So, what can we actually learn from this? What can we do better? Thanks Lukas -- Lukas Ocilka, Systems Management Team Leader & YaST Product Owner SLE Department, SUSE Linux 🌲 Please consider the environment before printing this e-mail ☂ Handle with care - Your reply can be stored in the cloud ⚠ IMPORTANT: The contents of this email and any attachments are confidential. They are intended for the named recipient(s) only. If you have received this email by mistake, please, notify the sender immediately and do not disclose the contents to anyone or make copies of thereof. -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
Dne 21. 12. 18 v 15:41 Lukas Ocilka napsal(a):
C. If it's a "sigh" one, then ... ?
With the happy new year 2019 I realized that it must have been this one :) All languages are weird. Including all spoken languages too.
So, what can we actually learn from this? What can we do better?
This part is still pending. I myself don't know. Lukas -- Lukas Ocilka, Systems Management Team Leader & YaST Product Owner SLE Department, SUSE Linux 🌲 Please consider the environment before printing this e-mail ☂ Handle with care - Your reply can be stored in the cloud -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
On 1/2/19 9:17 AM, Lukas Ocilka wrote:
Dne 21. 12. 18 v 15:41 Lukas Ocilka napsal(a):
C. If it's a "sigh" one, then ... ?
With the happy new year 2019 I realized that it must have been this one :) All languages are weird. Including all spoken languages too.
So, what can we actually learn from this? What can we do better?
This part is still pending. I myself don't know.
I think that it is a good thing to know about that weird String class API. In general, we should be alert when using String#+ operator, mainly when old code is automatically refactored. var1 +var2 should be avoided and always to use var1 + var2.
Lukas
-- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
Dne 02. 01. 19 v 10:17 Lukas Ocilka napsal(a):
Dne 21. 12. 18 v 15:41 Lukas Ocilka napsal(a):
C. If it's a "sigh" one, then ... ?
With the happy new year 2019 I realized that it must have been this one :) All languages are weird. Including all spoken languages too.
So, what can we actually learn from this? What can we do better?
This part is still pending. I myself don't know.
Always use some additional checks: unit tests, rubocop or at least the syntax check with "ruby -wc". But be careful, the syntax check just prints a warning and does not fail so do not relay on that in automatic checks (Travis), on the other hand Rubocop fails by default. And the Rubocop's message is a bit more understandable: Offenses: weird.rb:17:14: W: Ambiguous positive number operator. Parenthesize the method arguments if it's surely a positive number operator, or add a whitespace to the right of the + if it should be a addition. puts foo +"bar" ^ BTW a similar issue also exists in the other languages, some time ago I did a stupid typo in a shell script: $ARGS="" The BASH syntax check ("bash -n") does not print any warning, you have to use the shellcheck to really find it: $ARGS="" ^-- SC1066: Don't use $ on the left side of assignments. Which reminds me I have written a draft email for the shellcheck announcement, I'll post it here... And just few minutes ago Martin found a syntax error in a Perl code which could have been found by "perl -wc". So we should really add some more automatic checks... -- Ladislav Slezák YaST Developer SUSE LINUX, s.r.o. Corso IIa Křižíkova 148/34 18600 Praha 8 -- To unsubscribe, e-mail: yast-devel+unsubscribe@opensuse.org To contact the owner, e-mail: yast-devel+owner@opensuse.org
participants (6)
-
Ancor Gonzalez Sosa
-
Josef Reidinger
-
José Iván López González
-
Ladislav Slezak
-
Lukas Ocilka
-
Stefan Hundhammer