Hello, new to Crystal here.
I have a larger example that I boiled down to just using Rand and RandBuilder for the Builder pattern, but was surprised when my mental model of the first snippet of code didn’t translate over to when using it with a struct instance variable.
def test(x : Int32) : String?
if x == 1
"wtf"
else
nil
end
end
x = test(1)
puts "typeof(x) OUTSIDE if x: #{typeof(x)}"
if x
puts "typeof(x) INSIDE if x: #{typeof(x)}"
end
OUTPUT:
typeof(x) OUTSIDE if x: (String | Nil)
typeof(x) INSIDE if x: String
Ideally, in the code below, Rand’s instance variable @s would be String and not String?, but I have it that way so that the puts inside of RandBuilder’s builder method will be outputted.
struct RandBuilder
@s : String?
def initialize(@s) end
def s(x : String)
@s = x
self
end
def build()
puts "typeof(@s) OUTSIDE of if @s: #{typeof(@s)}"
if @s
puts "typeof(@s) INSIDE of if @s: #{typeof(@s)}"
Rand.new(@s)
else
raise "MUST provide @s when constructing a Rand struct"
end
end
end
struct Rand
@s : String?
def initialize(@s) end
def self.builder()
RandBuilder.new(nil)
end
end
result = Rand.builder().s("rand_Str").build()
puts "Builder result: #{result}"
OUTPUT:
typeof(@s) OUTSIDE of if @s: (String | Nil)
typeof(@s) INSIDE of if @s: (String | Nil)
Builder result: Rand(@s=“rand_Str”)
Without Rand’s instance variable @s being set to String?, the following error is received:
error in line 26
Error: instance variable ‘@s’ of Rand must be String, not (String | Nil)
Not really sure what posting this will yield, but I felt I should.
EDIT:
Just a few moments later I thought to google ‘crystal lang typecasting’
Changing the build method to this makes it work in the way that I’d want it to:
... all other code unchanged
def build()
puts "typeof(@s) OUTSIDE of if @s: #{typeof(@s)}"
if @s
puts "typeof(@s) INSIDE of if @s: #{typeof(@s)}"
Rand.new(@s.as(String))
else
raise "MUST provide @s when constructing a Rand struct"
end
end
... all other code unchanged
OUTPUT:
typeof(@s) OUTSIDE of if @s: (String | Nil)
typeof(@s) INSIDE of if @s: (String | Nil)
Builder result: Rand(@s=“rand_Str”)