[erlang-questions] Elixir Protocols in Erlang & a Strange Warning

Richard A. O'Keefe <>
Mon Dec 16 04:08:11 CET 2013


On 13/12/2013, at 7:31 PM, Kaveh Shahbazian wrote:

> I wanted to write something like ((IStringer)object).ToString() (in C#) in Erlang.

Can you make it a little bit clearer exactly what it is you
need to do?

There is a fundamental distinction between the way
something like
	object.toString()
works in OO languages
	to_string(Object)
works in Erlang:
- in the OO languages the "object" is in charge of what
  .toString() means
- in Erlang, the _function_ is in charge of what to_string()
  means.
> Then I came up with this idea/code in Erlang - which is nice enough to me like:
> 
> ?stringer(my_val):to_string().
> 
> 1 - Why nobody use this or promote things based on stateful modules in Erlang?

Where do you get "stateful" from?  An Erlang parameterised module
is a *value*.

In this case, "my_val" is *still* not in charge of what to_string
does.

In any case, one way to begin to understand parameterised modules
in Erlang is to start by thinking of

	-module(foo, {X,Y,Z}).
	-export([to_string/0]).
	to_string() -> 

as if it were something not entirely unlike

	-module(foo).
	-export([new/1,to_string/1]).
	new({X,Y,Z}) -> {foo,X,Y,Z}.
	to_string(This = {foo,X,Y,Z}) -> ...

There is, in short, no fundamental theoretical or practical difference
between

	stringer(my_val):to_string()

and

	stringer:to_string(my_val).

Anything you can do with the first you can CERTAINLY do with the second.

If you want to simulate OO in Erlang,
(1) lie down until the feeling passes off;
(2) if the condition persists, see a doctor (of CS);
(3) if the cure is unsuccessful,
	represent an "object" by a tuple
	{tag,Funs,Data}
    where Funs is a tuple of functions shared by a number of
    instances (yes, it's a vtable), and write

	to_string(Obj = {_,{...,TS...},...}) ->
	    TS(Obj).

I am deadly serious about (1).

When you using ((IStringer)object).to_string()
you are literally saying

	I don't know and I don't care what object
	is as long as it conforms to the IStringer
	interface.  I don't know and I don't care
	what the .to_string() method does as long
	as it has the right kind of arguments and
	results; it could reformat my hard drive,
	it could send threatening messages to the
	president of the USA, it could burn down
	the local hospital, I really really DON'T
	CARE.

If that's not what you mean, then perhaps you'd better write
your code another way, even in C#.  Any time you pass around
something with pluggable behaviour, ideally you need a strong
type-AND-EFFECT system that lets you limit the damage that
can be done, or at the least you need comments saying what is
supposed to be allowed.

I'm actually serious about (2) as well: see if you can find
a copy of "Why Joe Hates OO" by our very own Joe Armstrong.

(For the record, I am not an anti-OO bigot.  I have spent way
too much of my time building a Smalltalk system I'm generally
quite pleased with to be _that_.  But I have come to dread
not knowing what an argument will do if I poke it, especially
in a multithreading context.)

> (OTP aside and from talking to some Erlangers they did not know that actually OTP is built around this!

They didn't know it because it isn't true.  For a long time Erlang
didn't have parameterised modules, then it did as an experiment,
and now it doesn't again.  OTP managed without them and does again.


> So really there is a need to change how Erlang is being taught and promoted. It's possible that I am confused.).

If you find yourself struggling to do things the language X way
in language Y, it's generally a better to look for an _idiomatic_
way to solve the underlying problem in language Y than to try to
warp language Y into acting like language X.  Just recently I've
seen a horrible example of a Prolog system being warped to be
more like JavaScript, to the applause of people who haven't
thought about the benefits of being able to use other Prolog
systems as well...

As one example, it's not unknown for an Erlang module that
defines a data type to export a format/1 and maybe format/2
for converting an instance to a string or writing it to a
stream.  Using

	snorkelwhacker:format(Monster)

makes it clear that Monster is supposed to be the kind of thing
that the snorkelwhacker module knows about; this might be one of
several things.


More information about the erlang-questions mailing list