Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rebinding variables in outer scopes in Elixir

I'm new to functional/immutable programming and I've hit a wall. I'm trying to implement a very simply deduplication function in Elixir to deduplicate stdin.

I have a very trivial implementation using Stream.transform/2 but my original implementation used Stream.filter/2 like this (this is dumbed down for example purposes) and I'm not sure I understand why it's not working:

hashes = HashSet.new

IO.stream(:stdio, :line)
  |> Stream.filter(fn(line) ->
      if HashSet.member?(hashes, line) do
        false
      else
        hashes = HashSet.put(hashes, line)
        true
      end
    end)
  |> Enum.each(&IO.write(&1))

The idea is clearly that there's a Set containing the lines read in, and it's updated on each loop.

Now, some debugging led me to the fact that hashes inside the filter callback is empty on each loop, so I guess it's not changing the outer variable? I believe I just want to rebind the variable on the outside, rather than the one inside the filter function. Is this possible?

I'm thinking that I'm hitting a scoping issue as demonstrated by this JavaScript (it's the only comparison I can think of):

var hashes = new Set();

arr.filter(function (element) {
    var hashes = something(element); // i.e. using var not using outer scope
});

Can anybody clarify exactly what is incorrect with the above implementation? Thanks in advance :)

like image 218
whitfin Avatar asked Oct 27 '25 10:10

whitfin


1 Answers

From https://elixir-lang.readthedocs.org/en/latest/technical/scoping.html#function-clause-scope:

Each function clause defines a new lexical scope: any new variable bound inside it will not be available outside of that clause

Because of how immutability and variables are implemented in Elixir, assigning to hashes inside your inner function is the same as binding to a new variable every time.

like image 199
manukall Avatar answered Oct 30 '25 01:10

manukall



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!