spinlock99
I always wind up not having private functions in my modules because you can’t test them. I really have a strong preference for TDD and - at this point - I can barely write a function without having a test first. I recently had a function that is stupid simple:
def char_value(char), do: char - ?@
The point is to convert an uppercase letter to a numerical value (i.e. A == 1, B == 2, etc…). This is just a helper function that I’d never want to expose outside of the module, it’s logic is very simple, but It was tricky (for me) to figure out that ?@ == 64 and gave me the value I want. I suppose I could have just made the function char - ?A + 1 but this is just an example of when a function (which should be private IMO) benefits from being tested.
Am I just thinking about private functions wrong? To me, a private function is a helper for simplifying the complexity of public functions in the module. Should I just think of private functions as functions that are themselves simple enough to not need a test?
Trending in Discussions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #security










Showing Posts 30 to 21- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
Asd
Unused private functions are not compiled in the module, therefore Repatch cant access their code to make them public in tests. Try using this private function in a public one
spinlock99
This looks really cool but I’m getting the following error
here’s the spec
Asd
It is possible in some cases. Compiler needs to be able to prove that (for example) in every possible case the code
f.()will be called with f equalsfn -> IO.puts "hello" end. In BEAM languages, it is very hard to come up with such proof.For example, if my code looks like
Compiler can prove that
adder(y).(x)always equals to(fn x -> x + y end).(x)or justx + y. (However, in order for this to happen, you need to add the@compile :inline)But if I do something like
Compiler can’t prove it. And it can’t prove it, because module X can change in runtime (due to hot-reloading) independently from Y, and this feature is a hard requirement of the runtime
That may sound like a problem, but honestly, runtime overhead of anonymous function dispatch is extremely low and can’t be noticed in any real world program. For example, the way your code fits into CPU cache has much more impact on performance, and this thing is nearly random.
Schultzer
Is there no way to make them static, I feel the majority of these functions are similar in a codebase?
Asd
Anonymous functions are “slower” because it is a dynamic dispatch: runtime needs to check that variable contains a function, this function has the correct arity and then, if this function holds context (it is a closure) it needs to provide it too.
But given how these anonymous functions can be optimized, there are no limits.
Schultzer
This would be great for anon functions, I’ll be doing some benchmarking with decode specialization in my SQL library and I’m expecting anon functions to be slower then named private functions.
Asd
Yeah, I misunderstood what you said.
That’s true, but you are one step away from overcoming this problem, because it is always possible to change one public function into one public function and the private function clone, like this:
Every compiler can do this automatically and this optimization is called “speculative specialization” and while it increases the module size, it is fairly cheap in all the BEAM languages and can be applied almost everywhere
hauleth
You are confusing upcoming Elixir gradual-type system and JIT type tracking where Erlang is able to omit some guards for private functions when it can guarantee that it will be called only with values that do not require type check. For example if you do:
Compiler need to keep guards in both functions, as it do not know if
bar/1will be called only with integer. However if we write it as:Then it can “deduce” that
bar/1is called only with integer (as it is private, and the only caller already checks if that is integer or not). So it can optimise second guard away, as it has guarantee that it is integer.Asd
All of them are possible. Anonymous functions are lifted (they used to be literally lifted, but now they are compiled in a different way, but logically it is still lifting). Public functions can also be compiled the way private functions are
The only difference I know is with inlining. First of all, inlining must be explicitly enabled. Then, if compiler sees that public or private function fits inlining heuristics, it inlines the function. The difference is that if private function was inlined in every place it’s called, the function is removed from the module body. While public function will remain there, because it can be called from other module.
That’s about it
Schultzer
Not true, there is a difference, it used to be that private functions took longer to compile due to more optimizations being applied, it has changed now to public functions being slower as they have to be exported.
I’m not sure that all the optimizations that is done with private functions are possible to do to public or even anonymous.
But I agree that in the end this is all about improving the compiler as it shouldn’t be like this.