ghoetker

ghoetker

New to elixir, would appreciate a code review very much

I’m very new to Elixir and hoped someone might have a few moments to check over my first Elixir program. It’s a pretty direct translation of a Racket program I wrote, so I would especially value any feedback on more effective or Elixiry approaches.

The purpose of the program is to ingest a BibLaTeX file (@bibfile), which will be processed and written out to @outfile. Processing involves

  • Regularizing the keywords (conveniently on lines starting "“Keywords = {”), so each keyword is separated by commas (rather than comma or semicolon) and capitalized
  • Passing all of other lines unchanged

For example,

@book{Snoopy-Dark-01,
  Author = {Snoopy},
  Keywords = {fiction; Unfinished Books},
  Booktitle = {It was a Dark and Stormy Night}}

should end up as

@book{Snoopy-Dark-01,
Author = {Snoopy},
Keywords = {Fiction, Unfinished books},
 Booktitle = {It was a Dark and Stormy Night}}

Pretty basic, but a good learning experience.

Thank you very much in advance. I’m really enjoying both the Elixir language and community.

defmodule BibCleaner do
  @bibfile "/Users/ghoetker/BibDeskPapers/masterbibliography.bib"
  @outfile "test_out.bib"
  @moduledoc """
  Clean BibLaTeX files
  """

  def clean do
    {:ok, data} = File.read(@bibfile)
    {:ok, file} = File.open(@outfile, [:write, :utf8])

    data
    |> String.split("\n")
    |> Enum.map(&process(&1))
    |> Enum.map(&IO.puts(file, &1))

    File.close(file)
  end

  defp process(astring) do
    cond do
      String.contains?(astring, "\tKeywords = {") ->
        astring
        |> String.replace_leading("\tKeywords = {", "")
        |> String.replace_trailing("},", "")
        |> String.split([", ", "; "])
        |> Enum.map(&String.capitalize/1)
        |> Enum.join(", ")
        |> (fn x -> "\tKeywords = {" <> "#{x}" <> "}," end).()

      true ->
        "#{astring}"
    end
  end
end

Most Liked

wmnnd

wmnnd

Instead of using cond, you could do this which seems a bit more Elixir-y to me:


  defp process(astring) do
    if String.contains?(astring, "\tKeywords = {"),
      do: do_process(astring),
      else: astring
  end

  defp do_process(astring)
    astring
    |> String.replace_leading("\tKeywords = {", "")
    |> String.replace_trailing("},", "")
    |> String.split([", ", "; "])
    |> Enum.map(&String.capitalize/1)
    |> Enum.join(", ")
    |> (fn x -> "\tKeywords = {" <> "#{x}" <> "}," end).()
  end

Was there any particular reason you were using "#{astring}"? It seems like this just creates a string that is identical to the previous string …

cdegroot

cdegroot

From a quick glance, lgtm. Having said that - and this has nothing to do with Elixir - if this is more than a one-off, I would parse that thing into some data structure, operate on the data structure, and then write it out to a string again. May be me, but I prefer to have the ugly string scanning stuff and the stuff I’m actually trying to accomplish separate :wink:

ghoetker

ghoetker

Thank you all very, very much.

Replacing cond makes a lot of sense. Not sure why I’d gone to "#{astring}", but just astring works just fine.

I agree that parsing into a data structure would make sense if I were doing anything more complex. Bib(La)TeX is infamous for being difficult to parse (in its defense, we’ve learned a lot in the 33 years since it was invented), so I’ve avoided that pain point for this simple task.

Very helpful and much appreciated. Thank you again.

Where Next?

Popular in Questions Top

beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; somethi...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New

We're in Beta

About us Mission Statement