1
votes

I am trying to write tests in Elixir that call Erlang code similar to this:

foo([{property_one = P1, property_two = P2}|_] = Rows) when P1 =/= P2 ->
erlang:display("function head one"),

foo(Rows) ->
erlang:display("function head two"),
Rows.

I think that an Elixir keyword list would be the correct data type to pass to this function, but I cannot seem to construct it properly. This is the code I'm trying to call it with:

:module.foo([[property_one: "A", property_two: "B"]])

But this code goes direct to function head two. Where am I going wrong?

Update: Going to git history for the file revealed that a record declaration had been dropped somewhere along the way. Modifying the code to:

foo([#record{property_one = P1, property_two = P2}|_] = Rows)

fixed all problems

2
Did you write the foo function? That first clause only matches a list starting with the tuple {property_one, property_two}. This should match it: :module.foo([{:property_one, :property_two}]). P1 will always be :property_one and P2 will always be :property_two with the current Erlang code.Dogbert
No, I didn't write the Erlang code, but I know that it takes in a record that has those properties and that they are not the first two listed. I'm trying to untangle a bit of a rat's nest and I'm not that up on Erlang to start with.KevDog
Does the original code have a record name before the { in the pattern? Records in Erlang are stored as plain tuples without property key names. To create Erlang records in Elixir, you should use the Record module as explained here: hexdocs.pm/elixir/Record.html.Dogbert
It is called from within another function that does have a is_record guard, but I'm not sure that what gets passed to this function is a record, there are a few list comprehension before it gets to this one. I'll try it as a record, thanks.KevDog

2 Answers

2
votes

There are two problems with your code. One as bitwalker mentioned is in your elixir code where you wrap your proplist into a list. The other one in your erlang code:

[property_one: "A", property_two: "B"]

translates to the following proplist in erlang:

[{property_one, <<"A">>}, {property_two, <<"B">>}]

What you probably mean to match in your erlang code is this (although it is hard to guess what exactly you want there):

foo([{property_one, P1}, {property_two, P2}|_] = Rows) when P1 =/= P2 

In general Keyword in elixir can not be translated to erlang' proplists since keys in erlang can be of any type but in elixir they have to be atoms.

If you have to have more general way of passing erlang proplists from elixir to erlang there is nothing stopping you from constructing them manually in elixir. This will work for example:

[{property_one, "A"}, {"property_two", "B"}]

Although above is not Keyword list it is still an erlang proplist.

1
votes

It looks to me like you are wrapping the argument in an extra list when calling foo - the function matches on a proplist, not a list of proplists.