Marking a function as not implemented

1,311 views
Skip to first unread message

Louis Pilfold

unread,
Nov 6, 2015, 3:54:25 PM11/6/15
to elixir-lang-talk
Hello!

What's the preferred way to mark a function as not yet implemented? I
wanted to `raise NotImplementedError`, but it seems that doesn't exist
in the standard library.

Cheers,
Louis

Peter Hamilton

unread,
Nov 6, 2015, 4:12:51 PM11/6/15
to elixir-lang-talk
For the Enumerable protocol, this is from the docs on count and member?:

If {:error, __MODULE__} is returned a default algorithm using reduce and the match (===) operator is used. This algorithm runs in linear time.


--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-talk/CAM-pwt5Me%3DfDs8uHJ5LVkrJC8O%3DfNBZDwh0rfEY7pTnhV_5shQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Kevin Montuori

unread,
Nov 6, 2015, 4:16:44 PM11/6/15
to elixir-l...@googlegroups.com
>>>>> "lp" == Louis Pilfold <lo...@lpil.uk> writes:

lp> What's the preferred way to mark a function as not yet
lp> implemented?

I usually return :not_implemented and let pattern matching do its thing.
Often my calling function will have thoughts about how it wants to
manage the situation. I'm not sure if this is preferred in Elixir but
it's a pretty standard Erlang idiom.

k.

--
Kevin Montuori
mont...@gmail.com

Alexei Sholik

unread,
Nov 6, 2015, 4:53:23 PM11/6/15
to elixir-l...@googlegroups.com
What's the preferred way to mark a function as not yet implemented?

What for?

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.

Louis Pilfold

unread,
Nov 7, 2015, 1:01:46 PM11/7/15
to elixir-lang-talk
Thanks Kevin! :)

Pedro Medeiros

unread,
Nov 8, 2015, 8:36:04 AM11/8/15
to elixir-l...@googlegroups.com
Alexei. Guess is a way to define a protocol.


For more options, visit https://groups.google.com/d/optout.



--
Pedro Henrique de Souza Medeiros
----------------------------------
Cel: +55 (61) 9197-0993
Email: pedr...@gmail.com

Beautiful is better than ugly,
Explicit is better than implicit,
Simple is better than complex,
Complex is better than complicated.

The Zen of Python, by Tim Peters

Message has been deleted

Richard B

unread,
Nov 8, 2015, 10:03:53 AM11/8/15
to elixir-lang-talk
If you use a Behaviour the compiler will fail to compile for you. A Protocol is not the right abstraction for this in my opinion.

Kevin Montuori

unread,
Nov 8, 2015, 11:20:10 AM11/8/15
to elixir-l...@googlegroups.com
>>>>> "pm" == Pedro Medeiros <pedr...@gmail.com> writes:

pm> Alexei. Guess is a way to define a protocol.

I use unimplemented function stubs as simple placeholders when I know
there's going to be a function but haven't gotten around to writing the
implementation yet, either because I don't know what the
implementation's going to be or because I want to name all the pieces of
a process before digging in to the details. Sometimes it's a useful
marker when someone else is going to do the actual implementation.

It's also useful when only partially implementing a spec, a REST API for
instance could then know to return a 501.

I don't mean to speak for the OP; just responding to the question that
was asked since there are legitimate uses for defined but unimplemented
functions. Returning or throwing :not_implemented is concise,
descriptive, and -- it seems -- pretty standard.

Alexei Sholik

unread,
Nov 8, 2015, 5:04:04 PM11/8/15
to elixir-l...@googlegroups.com
That's a great example, Kevin, and also what I had in mind when I asked the "what for" question myself. I then asked the same question in this thread to see if the OP had, by any chance, something else in mind.

I have to disagree about returning :not_implemented though. It is assuming that the caller will fail on such a function because it will try to match on the return value. But as the author of the function, you may have little certainty of where it will be called by you or, perhaps, someone else. So there's an undesirable possibility here that the returned value will be assigned to a variable and cause havoc or result in the program functioning incorrectly, which is even worse.

I would always raise in this case, to intentionally disrupt the normal flow of the program. And IMO it's not necessary to define a custom exception, those are only meaningful when you expect the exception to be caught by a caller. The following is what I would likely use to convey the appropriate message:

  def some_func(_arg) do
    raise "Not Implemented. See the docs, Section 4.3.2.1. kthxbye (hint: you're supposed to override this"
  end

or, when something is simply not finished,

  def some_func(_arg) do
    raise "Not Implemented. And never will be. Sorry."
  end

or, if we're talking about partially implementing something, we need to let the user the ability to return a meaningful error message to the user, so I'd probably user throw in this case:

  def some_func(_arg) do
    throw {:not_implemented, :had_little_time}
  end

It is generally accepted that a throw can be catched as part of the normal flow of a program.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.

René Föhring

unread,
Nov 8, 2015, 5:37:01 PM11/8/15
to elixir-lang-talk
I would agree and disagree at the time with both Kevin and Alexei, but think that the solution might be right in the middle.
 
A: Raising an Exception to break normal execution flow. It is my understanding that this is not desired in the Elixir/Erlang ecosystem.
B: Returning something like :not_implemented. This is very much the idiomatic way, but lacks further information for the programmer who runs into it (and who might be unfamilar with our function's return values).

One solution might be returning a tuple: {:not_implemented, "See the docs, Section 4.3.2.1. or ask @martin (hint: you're supposed to ..."}

The benefits here are: 
- idomatic Elixir code
- Process probably crashes, intentionally disrupting the normal flow of the program
- the "no clause matches" error contains our human readable explanation

But I guess it really depends on the level of control you have over the codebase ...

Just my two cents
René

Louis Pilfold

unread,
Nov 8, 2015, 6:44:59 PM11/8/15
to elixir-lang-talk

Robert Virding

unread,
Nov 8, 2015, 7:42:01 PM11/8/15
to elixir-lang-talk
Raising exceptions is in fact very much the Erlang way to signal errors or situations where it impossible to continue. It forces the system to be designed in such a way as to handle this, which it should be anyway to handle errors. Only return an error value if is reasonable for the caller to do something sensible otherwise you are back to defensive programming which we strive to avoid.

Robert

Ben Wilson

unread,
Nov 8, 2015, 8:01:06 PM11/8/15
to elixir-lang-talk
Yeah I'm in the raise camp. Calling a function that cannot possibly do anything of use should not fail silently. You want to fail that as early as possible. Any code path that hits such a function is doomed to failure, you may as well make that as visible as possible.

René Föhring

unread,
Nov 9, 2015, 3:18:41 AM11/9/15
to elixir-lang-talk
Hi Robert,

> Raising exceptions is in fact very much the Erlang way to signal errors or situations where it impossible to continue.

yeah, I was probably unclear (and wrong) about that. :( 

I was jumping to the conclusion that Louis asked his question for his Dogma project, where I am involved as well. I deduced that he wants this behaviour for running a set of code analysis rules where some of them have not been implemented yet. In that case, the "Runner" should just go on with the next thing to process, I think it makes sense to work with a return value.

So, from your experience, am I right to presume that we would use the return-value-approach in recoverable situations (like the one I thought this was for) and the raise-approach in fatal ones (e.g. when a mandatory config file is just not there and the application cannot continue without it)?

Best,
René

Robert Virding

unread,
Nov 10, 2015, 5:31:09 PM11/10/15
to elixir-lang-talk
On Monday, 9 November 2015 09:18:41 UTC+1, René Föhring wrote:
Hi Robert,

So, from your experience, am I right to presume that we would use the return-value-approach in recoverable situations (like the one I thought this was for) and the raise-approach in fatal ones (e.g. when a mandatory config file is just not there and the application cannot continue without it)?

That is what I think is best. You just have to be sure that you can pattern match easily to see if the return value signifies a good or bad return. Also it then gives you an easy option to fail on a bad return value:

{:ok,value} = maybe_bad_fun( ... )

Not everyone agrees with this, some say you should always raise an error and use try-catch to handle the cases where you can continue. I find this solution harder to manage.

Robert
 
Reply all
Reply to author
Forward
0 new messages