h = []
# --------------
h[0] ||= "" # if h[0] was exists, use that h[0]
["foo", " bar"].each {|e| h[0] << e }
p h # => ["foo bar"]
h is a Array(String), i want to update h[0] in the loop, how to do same things (or achieve a similar effect) in Crystal? (I do know String is immutable, but Array is not, right?)
EDIT: I try like this, not work.
h : Array(String)
h[0] = h[0]? || ""
["foo", " bar"].each { |e| h[0] = h[0].insert(-1, e) }
p h # => ["foo bar"]
In src/1.cr:21:1
21 | h[0] = h[0]? || ""
^
Error: read before assignment to local variable 'h'
can you please just look at the official language reference before making all the obvious questions?
the syntax for initialize new array is [] of Type, thatās one of the first thing you need to learn in order to use crystal.
I know that this could be serve as some references to people that new to crystal (so they can just google the result) but I think you are making a lot of noise recently.
Obvious this problem has nothing to do with empty arrays.
h = [] of String
h[0] = h[0]? || ""
I did describe the problem not very well, i need improve it.
I think you are making a lot of noise recently.
Sorry for make you into trouble.
I ask question here instead of on discard or slack, just because the newcomer can search the correct answer here, because almost all my questions have not bad answers, I admit that some questions are a bit elementary, thatās also because I really canāt find useful results on google, ruby or somewhere, and to be honest, also hope the forum looks more active too, I guess anyone who loves Crystal donāt want to see that the many user last post in the forum was 4 months ago.
And I really donāt think most of my questions are elementary, those likely the issues will occur when a skilled Rubyist getting started with Crystal, although, because i am porting a 2000+ LOC ruby gem into Crystal, meet a lot of issue in a short period time, so ask a lots of question here lately indeed.
I will ask less questions, i hope my question can help other newcomer people a lot.
EDIT: I read ALL official document and one ebook before ask those question, and took a lots of note, most of the question are not mention in the document, or not implemented, and i answer people questions too as much as possible.
Sorry for this question even confusing myself a lot, i really should think carefully before ask this question.
If you try to put a value in an array, but that index is out of bounds, you get an IndexError. Check the docs:
Yes, this really surprised me, i do know IndexError, but happen on empty array is ignored, thank you.
Why do you check whatās in index zero, if itās clear that the array is empty?
Hope following ruby code describe my question more clearly
h = []
x = ["foo", " bar"].each # just ignore this part.
y = ["foo", " bar"].each
loop do
h[0] ||= "" # <= the h here may or may not be empty.
h[0] << x.next
# h[1] ||= "" # probably add one or two element, but we don't know before the loop.
# h[1] << y.next
end
p h # => ["foo bar"]
So, is it possible use Crystal rewrite that? probably h << "" not work in the loop for this case?
I hope following code can work, but as describe by asterite, index is out of bounds,
h = [] of String
x = ["foo", " bar"].each # just ignore this part.
loop do
h[0] ||= "" # <= the h here may or may not be empty.
_x = x.next
break if _x.is_a? Iterator::Stop
h[0] += _x
end
p h # => ["foo bar"]
But it works if h is a hash, following is expected answer.
h = {} of String => String
x = ["foo", " bar"].each # just ignore this part.
loop do
h["foo"] ||= ""
_x = x.next
break if _x.is_a? Iterator::Stop
h["foo"] += _x
end
p h # => ["foo bar"]
Is that literally the code that you are trying to port?
Becauseā¦ the array h starts empty. But as soon as the loop starts thereās this:
h[0] ||= ""
That means āif thereās nothing in position 0, put an empty stringā[
So why not have h already start with that empty string?
Also, what do you need the strings for? If they are for building a string in a loop, you better use IO::Memory or String::Builder.
Also, this can be translated to Crystal:
h[0] ||= ""
The equivalent is:
h << "" if h.empty?
(I already said that in a previous post)
Also the loop kind of doesnāt make sense at allā¦ why use .each to traverse the strings and build another string. It looks to me that doing x.join would be equivalent.
All of that to sayā¦ itās always better to post the full snippet of code you are trying to translate, otherwise everyone helping you will be a bit blind somewhere, and given unhelpful messages most of the time.
Very sorry for confusing. please just ignore my first array version example, itās what i imagined, the original code actual use Hash, for the purpose of reduce code, i translate it into array, but i do wrong.
for curious, original version code is here, new my fixed version is here.
as you can see, i solved my issue based on peopleās help.
h << āā if h.empty?
Just for clarify, i do think h << "" if h.empty? not equivalent to the h[0] ||= "" one for my dirty code when i saw your post, , because it could not match the original example.
See the comment in the following code.
h = [] of String
x = ["foo", " bar"].each # just ignore this part.
y = ["foo", " bar"].each # just ignore this part.
loop do
h << "" if h.empty?
_x = x.next
break if _x.is_a? Iterator::Stop
h[-1] += _x
# How about if want add a y.next to h[-2]?
# h[-2] << y.next
end
p h # => ["foo bar"]
Also, what do you need the strings for? If they are for building a string in a loop, you better use IO::Memory or String::Builder.
Yes, this is the big part i need to change my way of thinking, i will read more code to investigate others for really use case.
Also the loop kind of doesnāt make sense at allā¦ why use .each to traverse the strings and build another string. It looks to me that doing x.join would be equivalent.