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

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
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
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
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
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
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
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement