When out is used as a variable's name there are unexpected results
require "openssl/cipher"
out = ""
string="test"
cipher = OpenSSL::Cipher.new("AES256")
cipher.decrypt
cipher.key = "somekey"
out = cipher.update(string)
puts typeof(out) # Slice(UInt8)
string = String.new(out, "utf-8") # expecting variable or instance variable after out
Syntax error in src/source.cr:36: expecting variable or instance variable after out
string = String.new(out, "utf-8")
$ crystal -v -1-
Crystal 0.20.5 (2017-01-25)
By the way, this happens only when "out" is used as a variable (apparently)
Is it a reserved keyword somehow?
I apologize if this is a user fault, I'm still learning and I'm not sure if this is a compiler or user error
Hi! Indeed, out is a reserved keyword. See: https://crystal-lang.org/docs/syntax_and_semantics/c_bindings/out.html.
I'm leaving this open because maybe we can link to that document from the syntax error message.
@asterite: as a general rule of thumb, what do you think about linking error messages to the Language Reference? I feel it is a good way of pointing users to relevant design aspects of the language while not bloating error messages.
I think either this code should be valid and allowed or the error should be given as soon as you do out = "". It's strange otherwise.
Yes indeed @lbguilherme, that was exactly my point.
There is no way a reserved keyword should be allowed to be used as a variable (and that's exactly what happens here).
In my opinion, the compiler should give an error as soon as an assignment (or variable declaration) is made
Hadn't noticed that detail. I agree, ideally the compiler should fail on the declaration.
Just wanted to test this, and it appear that the out rule is buggy on usage in implicit return:
def func
out = "bla"
out.size
end
puts func # => 3
What do you mean by buggy? I think it's the same issue that we've been discussing: there's no conflict using "out" as a variable as long as you don't try to use it as a param to call another function or method.
Then the compiler assumes you're using the out keyword and expects a variable name after that.
I don't think it's buggy, it's just a bit confusing/surprising. So maybe we should do as @lbguilherme suggests and just throw an error as soon as you do out = "bla" :).
@mverzilli you're right, not buggy, but kinda confusing/surprising.
out = "bla" being an error is good to me
It would also be a possible solution to allow out as variable name and don't complain about the above code. According to the documentation it should be easily to distinguish between out as a keyword (when followed by a variable or instance variable) and as a variable name.
I don't think this could lead to any problems. Although it is questionable if a keyword should be allowed as variable name at all, even if it is unambiguous.
Also I think we need to error for out as a method name:
def out(foo)
pp foo
end
out 1 # works
out(out 1) # error: expecting variable or instance variable after out
I think that it's confusing that it works sometimes only. Having a proper error message when trying to define a method named out would resolve this.
Most helpful comment
I think either this code should be valid and allowed or the error should be given as soon as you do
out = "". It's strange otherwise.