Puts seems to break the code, why?

Hi i am new to crystal so i rely heavily on puts to see how it works…
The code below is total nonsense, i just tried to find an easy example to share
if i remove the comment in line 14 and do a puts i get a different result.
Is it a bug or can somebody explain this… or maybe both.

io = IO::Memory.new("0123456789")
pos = 0
myArray = Array(Char).new
even = "02468"
containsfive = false
io.each_char do |char|
    
    if even.includes?(char)
        if containsfive
            next
        end
        myArray << char
    elsif
        #puts "uneven " + pos.to_s
        if char == '5'
            containsfive = true
        end
    end
    pos +=1
end

myArray.each do |char|
	puts char.to_s
end

in case that this is a bug… i am on
Crystal 1.5.0 [994c70b10] (2022-07-06)
LLVM: 10.0.0
Default target: aarch64-apple-darwin

This looks very suspiciously like a codegen bug. I’m pretty sure it’s not expected or explainable behaviour.

It seems to be indendent of the target platform, it reproduces on x86_64-linux as well.

Thanks for the fast reply!
Since i don’t have any experience with ruby either i am always a bit confused about having no parenthesis for function parameters…

i tried to replace the puts with a function like

def prints(something)
    something.each_char do |char|
        print char
    end
    print '\n'
end

result is the same, but if i just assign a var right before the if like

test = true
if char == '5'
...
end

everything is fine.

prints "uneven"
test = true
if char == '5'

it breaks again…
I don’t know but it seems that every form of print is like finishing the elsif.

For debugging i just write the puts to the end of the block…

Could you please run crystal tool format file.cr on the file, with the commented line, and with the line uncommented? I’m pretty sure that once you do that the answer will reveal itself.

Note that you are doing something like:

if ...
elsif (if ...)
end

which is pretty strange!

4 Likes

Put another way: you have an elsif instead of an else. Look out!

Oooh, good catch. I was completely oblivious to the elsif. It’s easy to miss and read as an else :see_no_evil:
Formatter definitely helps :+1:

Whenever I try code I paste it in my editor, and that’s configured to run the formatter. The second I pasted the code I noticed there was something wrong :-)

I really recommend everyone to use the formatter in their editor. Not only for beautifying code, but because it reveals these mistakes very easily.

For example:

puts 1
a = puts 1,
b = 2
puts b

Do you notice something wrong with the code above?

Running the formatter you get this:

puts 1
a = puts 1,
  b = 2
puts b

Oh, look! The b = 2 became indented, because it’s inside a call (there’s a trailing comma in the previous line.)

3 Likes

Uuuuh thanks,
now i see it…
but i felt that something is wrong nonetheless.
I might have expected an compiler error.
But ok the newline is not a ; and every expression has a return value.
I was still not convinced. But the manual says:

The only falsey values are nil , false and null pointers (pointers whose memory address is zero). Any other value is truthy.

So everything makes sense and i have learned a lot from this mistake :slight_smile:

Thanks again!

I do same things always too, i config to format all language in my emacs use C-c C-c, that probably is the reason why i really don’t like language respect indent, e.g. Python.


BTW, @asterite, any update on this? crystal tool format no-op if indentation error on macro · Issue #12164 · crystal-lang/crystal · GitHub