This question already has answers here:
Dynamic constant assignment
(7 answers)
Closed 2 years ago.
I am trying to make a game for ruby but I keep getting the following error at PlayerMove = $STDIN.gets.chomp:
dynamic constant assignment error
I tried changing the front of $STDIN to STDIN to gets.chomp and nothing seems to work.
$Health = 100
$OPHealth = 50
def fight
def NumberN
$RandomNumber = ran(0..30)
end
def Player
print ">"
PlayerMove = gets.chomp
if PlayerMove.downcase == "attack"
RandomNumber - OPHealth
puts "You attach the Spider and do #{RandomNumber} Damage,\n he has #{OPHealth}"
elsif OPHealth >= 0
puts "The SPIDER IS DEAD"
ENDGAME()
elsif Health >= 0
puts "Your dead GAMEOVER you abomination"
else
puts "You need to attack"
Player()
end
end
This particular issue will be with the case you're using: for variables, Ruby uses lower snake case.
Update your code's variables to use, for example: player_move = gets.chomp and this will resolve the error.
Using upper camel case as you are is reserved for classes and modules (with constants typically using upper case). (I'm sure I'm missing something here - let me know if anyone can correct me.)
Therefore, assigning values as you are is throwing the "dynamic constant assignment error" you mention.
Have a bit of a read up on this: global variables prefixed with $ are also seldom seen. This style guide is quite a good resource for this.
That said, simply updating the variables won't fix this in its entirety - you'll need to look at the the scoping and structure of your code before this will work. When you run into another issue, see how you get on and if you can't fix it, pop it into another question.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I'm making a simple CLI in Ruby and I'm having the user to input a "Y" or "N" but right now the program is only working if they type this in upper case. I'd like it to work regardless of case. I tried using "N".casecmp or "Y".casecmp but that is giving me an argument error. Any ideas? Do I need to require something in environment?
Maybe showing my code would help?
if input == "Y"
method_a
elsif input == "N"
Adding .casecmp? or .casecmp either sends me in an infinite loop or gives me an argument error.
You can use the method of string downcase and you can forget the problem of uppercase, so u can check for y or n now.
Doc: https://apidock.com/ruby/v2_5_5/String/downcase
Example:
"hEllO".downcase #=> "hello"
Should work with casecmp? without explicitly mutating original string
String.casecmp?
Returns true if self and other_string are equal after Unicode case
folding, otherwise false:
given = "Hello"
expected = "hello"
ok = given.casecmp?(expected)
puts ok ? "Ok" : "Not" # => "Ok"
i think between 'y' or 'Y' input have their own object_id.
So they are actually different object.
So i think it's not about the input, this is about what we gonna do from the input.
If you try to make comparison to your input regardless their case, casecmp should do the trick
a = gets.to_s
if a.casecmp('Y').zero?
# do stuff
elsif a.casecmp('N').zero?
# do stuff
else
# do stuff
end
https://apidock.com/ruby/String/casecmp
'y'.casecmp('Y').zero? # true, then it is same regardless case
'Y'.casecmp('y').zero? # true
This question already has answers here:
Ruby instance method & conditional local variable assignment with same name
(2 answers)
Closed 3 years ago.
I wanted to use the classical ||= re-assignment (cf Set Ruby variable if it is not already defined) with ActiveInteraction pretty much like in https://github.com/AaronLasseigne/active_interaction/issues/395
However by testing different syntaxes in ActiveInteraction I stumbled upon a much more peculiar issue that happens even in vanilly Ruby.
A non-executed line (blocked by a if false) can still have a major impact on the rest of the code:
class A
attr_accessor :a
def run
(puts defined? a; a) if true
end
def run2
(puts 'change a'; a = 0) if false
puts defined? a
a
end
end
x = A.new
x.run # "method"; nil
x.run2 # "local-variable"; nil
x.a = 5
x.run # "method"; 5
x.run2 # "local-variable"; nil
Can anyone explain if this is a bug or a feature? And if a feature: how come? It seems very odd.
EDIT: Thanks to the answer of #Sergio Tulentsev I managed to find that my question is pretty much a duplicate of Ruby instance method & conditional local variable assignment with same name with a different focus for the title name.
[is this] a bug or a feature?
Neither. It's a... peculiarity. What happens is, when parser sees assignment to local variable in the code, it goes ahead and adds the name to the scope (starting from that line, possibly shadowing other names, like your method here). With default value of nil. If the actual assignment is then never executed, the new local variable is still in scope and still evaluates to nil.
This is documented in https://docs.ruby-lang.org/en/2.5.0/syntax/assignment_rdoc.html#label-Local+Variables+and+Methods.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Alright, I have tried my best to get this code to just run without spitting out errors, but to no avail. Hopefully you can help me out.
require 'launchy'
#def linebreak(breakline)
def program()
puts "Welcome to test program v1. Would you like to continue? ENTER y for Yes or n for no"
user_input_1 = gets.chomp
if user_input_1 == "y"
puts "How would you like to proceed CRASH | TEXTMAKER | UNDECIDED // CASE SENSITIVE"
user_input_2 = gets.chomp
if user_input_2 == "CRASH"
while true Launchy.open("http://google.com")
elsif user_input_2 = "TEXTMAKER"
while true out_file.puts("test program v1")
else
puts "You have not entered a method."
elsif user_input_1 == "n"
abort
else
puts "That is not a valid command. Please run the script again."
end
end
Alright there's a few problems, but don't worry everything can be
fixed!
Let's start with what you did well
Good job using your booleans in most cases, most beginners don't seem
to grasp that == means equal, and = means something completely
different
Good job with the puts and using it properly, there are other
methods which I will cover later, that will look much better in your
case.
Now let's cover what can be fixed
As I stated above in most cases you used your Boolean correctly
however you seem to have missed one. elsif user_input_2 = "TEXTMAKER" you need a == to show that it is equal.
Your while loop doesn't seem to make any sense because you don't ever really set anything as true. In Ruby it is highly
recommended to never use a while loop, of course there are times
that you have to, but only after you've tried everything else.
elsif; else; elsif never use an elsif after an else. elsif is to provide an exception, in your case there's more then
one option so use the elsifs before the else, you'd be better using a case statement here.
Not to sound like an ass, but your indentation is horrible. You'd find a lot more problems with good indentation, in Ruby that's two
spaces, here's the style guide:
https://github.com/bbatsov/ruby-style-guide
Never have your users options be case sensitive, if somebody else is going to use your program, just assume they are the dumbest people in the world and make it super easy for them. user_input_2.gets.chomp.upcase this will set it so that no matter how they enter their text, it will always be upper case.
You're missing an end this will become clear once you've used proper indentation
Alright let's rewrite this thing:
require 'launchy'
def program #<= you don't need the parentheses
print "Welcome to the test program version 1, to continue type 'c' to exit type 'e': "
user_input = gets.chomp.upcase
if user_input == "C"
program_choices
elsif user_input == "E"
puts "Exiting.."
exit
#if you really want to use abort
#abort("Exiting..")
#you won't need to use exit if you use abort
else
puts "Invalid input, try again"
program #<= this is a loop known as recursion, don't use it to much
end
end
def program_choices
print "Pick an option, the choices include CRASH | TEXTMAKER | UNDECIDED: "
user_input = gets.chomp.upcase
case user_input #<= this is how you start a case statement
when "CRASH"
Launchy.open("http://google.com")
when "TEXTMAKER"
write_test_data
when "UNDECIDED"
puts "You really need to make up your mind.." #<= have some fun with it, that's the point of programming.
program_choices
else
puts "Invalid input, try again"
program_choices
end
end
def write_test_data
x = "Test file version 1"
if File.exist?("path/to/test/file.txt")
File.open("path/to/test/file.txt", "a"){ |s| s.write(x) }
else
new_test_file = File.new("path/to/test/file.txt")
new_test_file.puts(x)
end
end
And bam! Your program is up and running! If you have any questions about anything don't hesitate to ask, programming can be very tricky, and it can be very hard. Keep it up and you'll get there!
I see plenty of problems.
This isn't valid:
while true Launchy.open("http://google.com")
Neither is this:
while true out_file.puts("test program v1")
I can't tell you how to fix this, though, since it's not at all clear what you're trying to do.
An if block may only have one else, and it must come after all elsifs.
Here:
elsif user_input_2 = "TEXTMAKER"
You're assigning a new value to user_input_2. I'm guessing you meant to use the equality operator, which is ==.
Your def block doesn't have an end. This became obvious after I edited your code to use proper indentation. You'll save yourself a lot of trouble by using sensible indentation and whitespace.
This question already has answers here:
Ruby while syntax
(2 answers)
Closed 7 years ago.
A while loop works with or without do. Please explain why the following two snippets works the same way.
Without do
i = 1
while i < 5
i = i + 1
end
With do
i = 1
while i < 5 do
i = i + 1
end
The non-theoretical answer is quite simply: because the Ruby Syntax Guide said so.
The language syntax guide defines the do keyword as optional for both while and until loops.
From what I understand - and it is mostly a theory - allowing the do to be optional rather than required is mostly for compatibility and allowing for harmonic syntax within the language.
I think of it as an acknowledgment for the "gray" areas, where things are less absolute. The same is done in physics, where light behaves both as a particle and as a wave and we should acknowledge both aspects.
Coming from different languages and school of thought, while is somewhere between a pure keyword (like if) and a method (like loop, which is defined under the Kernel module)
if statements do not require a do to begin a block of code and under the same logic, while loops wouldn't require a do keyword.
This is while as a keyword.
On the other hand, loop requires the do keyword (or the {block}), so why shouldn't while have the same semantics?
This is while as a method (as far as syntax goes).
Ruby is about making the programmer happy. Allowing the do to be optional makes all programmers happy and doesn't require that the Ruby programmer resign themselves to just one school of thought related to the nature of while.
x = 0
while x<3 do puts "hello"; x+=1 end
--output:--
hello
hello
hello
The do is optional, and can be used to clarify a code as in the answer to be on one line. Separation can be done with a do, newline, \, or semicolon.
I'm playing around with Ruby and trying create a little bank account program. When I run this particular line of code which is running withing the create_account:
unless #response.is_a? Integer && #response.to_str.length == 4
puts "Your response must be 4 numbers in length."
create_account
else
#pin = #response
puts "Your pin has been set."
end
I get this response:
bank_account.rb:24:in 'is_a?':class or module required (TypeError)
from bank_account.rb:24:in 'create_account'
from bank_account.rb:47:in '<main>'
I can't exactly figure out what's going on, but I'm including the rest of my code. It's incomplete, obviously because I'm stuck on this part. I go through a while loop and enter 'Create Account' to start the create_account method. My goal is to run the conditional and require the user to type a 4 digit integer, like any ole pin number. If it is not an integer nor 4 digits in length, I call the create_account method to get them to start over.
I'm running ruby 2.0.0 if that information is necessary, but I wager it is likely more to do with my code. Stackoverflow is new to me, so I apologize if this question has been asked. I tried to do my homework as is advised before asking a question, but I'm still stumped. Any help is appreciated.
You need to put the class Integer in parentheses:
unless #response.is_a?(Integer) && #response.to_str.length == 4
You are actually evaulating is_a? on (Integer && #response.to_str.length == 4) which is a boolean value, not a class or module.