How do I push to an existing array?

1,373 views
Skip to first unread message

Eric Berry

unread,
Jul 10, 2015, 9:59:57 AM7/10/15
to elixir-l...@googlegroups.com
I'm VERY new to Elixir so forgive me for dumb questions. Here's a simple tool I am playing with to build keywords. I am doing something wrong, but the error message is not very clear.

Code:

defmodule Simple do
  def build_keywords do
    keywords = ["Car Insurance", "Insurance Car", "Car Ins", "Insurance Quote", "Insurance", "car Insurance Quote", "Insurance Car Quote", "I need Car Insurance"]
    state = "UT"
    cities = ["Alpine", "Altamont", "Alton", "Altonah", "American Fork", "Aneth", "Annabella", "Antimony", "Aurora", "Axtell", "Bear River City", "Beaver", "Beryl", "Bicknell", "Bingham Canyon", "Blanding", "Bluebell", "Bluff", "Bonanza", "Boulder", "Bountiful", "Brian Head", "Brigham City", "Bryce", "Bryce Canyon", "Cache Junction", "Cannonville", "Castle Dale", "Cedar City", "Cedar Valley", "Centerfield", "Centerville", "Central", "Chester", "Circleville", "Cisco", "Clarkston", "Clawson", "Clearfield", "Cleveland", "Coalville", "Collinston", "Corinne", "Cornish", "Croydon", "Dammeron Valley", "Delta", "Deweyville", "Draper", "Duchesne", "Duck Creek Village", "Dugway", "Dutch John", "Eagle Mountain", "East Carbon", "Echo", "Eden", "Elberta", "Elmo", "Elsinore", "Emery", "Enterprise", "Ephraim", "Escalante", "Eureka", "Fairview", "Farmington", "Fayette", "Ferron", "Fielding", "Fillmore", "Fort Duchesne", "Fountain Green", "Fruitland", "Garden City", "Garland", "Garrison", "Glendale", "Glenwood", "Goshen", "Grantsville", "Green River", "Greenville", "Greenwich", "Grouse Creek", "Gunlock", "Gunnison", "Hanksville", "Hanna", "Hatch", "Heber City", "Helper", "Henefer", "Henrieville", "Herriman", "Hildale", "Hill Afb", "Hinckley", "Holden", "Honeyville", "Hooper", "Howell", "Huntington", "Huntsville", "Hurricane", "Hyde Park", "Hyrum", "Ibapah", "Ivins", "Jensen", "Joseph", "Junction", "Kamas", "Kanab", "Kanarraville", "Kanosh", "Kaysville", "Kenilworth", "Kingston", "Koosharem", "La Sal", "La Verkin", "Lake Powell", "Laketown", "Lapoint", "Layton", "Leamington", "Leeds", "Lehi", "Levan", "Lewiston", "Lindon", "Loa", "Logan", "Lyman", "Lynndyl", "Magna", "Manila", "Manti", "Mantua", "Mapleton", "Marysvale", "Mayfield", "Meadow", "Mendon", "Mexican Hat", "Midvale", "Midway", "Milford", "Millville", "Minersville", "Moab", "Modena", "Mona", "Monroe", "Montezuma Creek", "Monticello", "Monument Valley", "Morgan", "Moroni", "Mount Carmel", "Mount Pleasant", "Mountain Home", "Myton", "Neola", "Nephi", "New Harmony", "Newcastle", "Newton", "North Salt Lake", "Oak City", "Oakley", "Ogden", "Orangeville", "Orderville", "Orem", "Panguitch", "Paradise", "Paragonah", "Park City", "Park Valley", "Parowan", "Payson", "Peoa", "Pine Valley", "Pleasant Grove", "Plymouth", "Portage", "Price", "Providence", "Provo", "Randlett", "Randolph", "Redmond", "Richfield", "Richmond", "Riverside", "Riverton", "Rockville", "Roosevelt", "Roy", "Rush Valley", "Saint George", "Salem", "Salina", "Salt Lake City", "Sandy", "Santa Clara", "Santaquin", "Saratoga Springs", "Scipio", "Sevier", "Sigurd", "Smithfield", "Snowville", "South Jordan", "Spanish Fork", "Spring City", "Springdale", "Springville", "Sterling", "Stockton", "Summit", "Sunnyside", "Syracuse", "Tabiona", "Talmage", "Teasdale", "Thompson", "Tooele", "Toquerville", "Torrey", "Tremonton", "Trenton", "Tridell", "Tropic", "Vernal", "Vernon", "Veyo", "Virgin", "Wales", "Wallsburg", "Washington", "Wellington", "Wellsville", "Wendover", "West Jordan", "Whiterocks", "Willard", "Woodruff", "Woods Cross"]
    auxs = ["in"]

    Enum.map(cities, fn(city) -> build_keywords_for_city(city, keywords, state, auxs) end)
  end

  def build_keywords_for_city(city, keywords, state, auxs) do
    results = []
    results = results ++ Enum.map(keywords, fn(keyword) -> map_keywords(keyword, city, state, auxs) end)
    Enum.map(results, fn(kw) -> IO.puts(kw) end)
  end

  def map_keywords(keyword, city, state, auxs) do
    results = []
    results = results ++ String.downcase(Enum.join([keyword, city], " "))
    results = results ++ String.downcase(Enum.join([keyword, city, state], " "))
    results
  end
end


Here's the results of my test:

  1) test build keywords (SimpleTest)
     test/simple_test.exs:8
     ** (ArgumentError) argument error
     stacktrace:
       :erlang.++("car insurance alpine", "car insurance alpine ut")
       (simple) lib/simple.ex:20: Simple.map_keywords/4
       (elixir) lib/enum.ex:977: anonymous fn/3 in Enum.map/2
       (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3
       (elixir) lib/enum.ex:977: Enum.map/2
       (simple) lib/simple.ex:13: Simple.build_keywords_for_city/4
       (elixir) lib/enum.ex:977: anonymous fn/3 in Enum.map/2
       (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3

Can somebody please let me know what I am doing wrong? I come from a Ruby background so I may be thinking too ruby-ish.

Thanks,

Eric

José Valim

unread,
Jul 10, 2015, 10:12:01 AM7/10/15
to elixir-l...@googlegroups.com
According to your understanding of Elixir so far, what does the ++ operator do? What should be its arguments? What does the documentation say about it?

PS: Btw, you want to send those e-mails to elixir-lang-talk. This mailing list is for discussion of core language features. We can discuss this one here but please send the next ones there.



José Valim
Skype: jv.ptec
Founder and Director of R&D

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/92b4c721-4d2c-4db8-ae0a-e0e7ed591c2f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Eric Berry

unread,
Jul 10, 2015, 10:25:52 AM7/10/15
to elixir-l...@googlegroups.com, José Valim
It was my understanding based on the docs that ++ joins arrays together (http://elixir-lang.org/getting-started/basic-types.html#linked-lists under linked lists)

"Two lists can be concatenated and subtracted using the ++/2 and --/2 operators:

I was corrected by @aaronm on the slack channel with the following example:


Thanks for your help. I will make sure I post to the correct place next time (likely slack overflow)

Eric
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/F9hTILGVnAg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KjAi0WOwL97yoJKRzLqnJYiRujLRZ5J9HP%3DRnmyOnMCg%40mail.gmail.com.

Stian Håklev

unread,
Jul 10, 2015, 10:28:32 AM7/10/15
to elixir-l...@googlegroups.com

Hi Eric,

it seems like you are trying to add a String to the List, but ++ only works on two lists. Also, you should generally avoid using ++ to add a single element to a list, because it has a poor performance. Instead, use the form [ head | tail ] (note that head must be a single element and tail must be a list). You can also use this form in pattern matching, for example

[ h | tl ] = [1, 2, 3]

after this, h will have the value of 1, and t of [2, 3]

But in fact, we don’t really need this in your code example, since we can just avoid all these intermediate variables anyway - which is idiomatic Elixir. We can directly construct the list to be returned, or use the pipe operator.

  def build_keywords_for_city(city, keywords, state, auxs) do
Enum.map(keywords, fn(keyword) -> map_keywords(keyword, city, state, auxs) end
)
    |> Enum.map(fn(kw) -> IO.puts(kw) end)
  
end

  def map_keywords(keyword, city, state, auxs) do

    [String.downcase(Enum.join([keyword, city], " ")), 
    String.downcase(Enum.join([keyword, city, state], " "))]
  end

I could probably rewrite your entire program quite a bit to make it more idiomatic, but since you were mainly concerned about the list addition (and I know how it is to begin learning a new language, and experiment with constructs etc), I made as few changes as possible.

Stian


--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/92b4c721-4d2c-4db8-ae0a-e0e7ed591c2f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
http://reganmian.net/blog -- Random Stuff that Matters

José Valim

unread,
Jul 10, 2015, 10:30:37 AM7/10/15
to elixir-l...@googlegroups.com
Yes, the mistake in your code was that you were calling ++ with String.downcase on the right side, which won't return a list but a string.

The code in the gist could also be improved:

for city <- cities,
keyword <- keywords,
entry <- ["#{keyword} #{city}", "#{keyword} #{city} #{state}"],
do: entry

No need for nested "for" nor for calling List.flatten/1.



José Valim
Skype: jv.ptec
Founder and Director of R&D

Reply all
Reply to author
Forward
0 new messages