Index of a string in a macro

Is there a preprocessor function that will allow me to access string characters by index? For example following code:

macro article(word)
{% word = word.downcase %}
{% vowel_sound = ["hour", "honest", "hour", "heir"] %}
{% consonant_sound = ["universuty", "unicorn", "use", "european", "one", "ouja"] %}
{{ return ["an", word] if vowel_sound.includes? word }}
{{ return ['a', word] if consonant_sound.includes? word }}
{% first_letter = word[0] %}
{{ ['a', 'e', 'i', 'o', 'u'].includes? first_letter ? (["an", word]) : (['a', word]) }}
end

Will give me the error:

Error: wrong argument for StringLiteral#[] (NumberLiteral): 0

Not quite elegant, but you can use first_letter = word[0..0], because the [] operator for macro string literals only seems to take ranges as argument.

1 Like

So I fixed the rest of the macro (as it can’t use return either):

macro article(word)
  {% word = word.downcase %}
  {% vowel_sound = ["hour", "honest", "honor", "heir"] %}
  {% consonant_sound = ["university", "unicorn", "use", "european", "one", "ouja"] %}
  {% result = nil %}
  {% result = "an" if vowel_sound.includes? word %}
  {% result = 'a' if consonant_sound.includes? word %}
  {% first_letter = word[0..0] %}
  {% if !result
       result = (['a', 'e', 'i', 'o', 'u'].includes?(first_letter) ? "an" : 'a')
     end %}
  {{ [result, word] }}
end

But now when it does not hit one of the exceptions (vowel_sound or consonant_sound), I’ll always get ‘a’. So I assume what happens is the first_letter is a range at this point..? Don’t I run into the same problem as with a string now?

The problem is that your array of vowels contains chars, but the [] operator always returns a new string instead of a char, which will always give a false when compared with the chars in your vowel array.

Changing your code to result = (["a", "e", "i", "o", "u"].includes?(first_letter) ? "an" : "a") will make it work.

1 Like

Thanks, I can continue coding on my D&D campaign c:

2 Likes

Glad I could help!

2 Likes

Antother alternative for retrieving a char at arbitrary position in a string literal is to transform it into an array of chars.

{{ "foo".chars[0] }} # => 'f'
2 Likes