Calling internal functions - foo::bar() ?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

Kostis Sagonas-3
Chandrashekhar Mullaparthi wrote:

 > Me too! I've tried wrapping the -compile(export_all) directive in
 > -ifdef(debug)/-endif and then use a Makefile to compile with the debug
 > option or not. But then I can't deliver this system to test as it is
 > not what will go live. So this feature would be immensely useful.

Being somebody who never used the -compile(export_all) directive
in his life, I really would very much like to understand why this
proposed addition would be "immensely useful" especially since
currently there are very nice alternatives:

        erlc +export_all File
or
        c(File, [export_all]).

which nicely do the trick (whenever *really* needed).

 > I'm afraid of removing the export_all from a module.

Hint: don't add it in the first place.

Kostis

 > > P.S., who can beat this?

Depends on your definition of "beat" :)

$ find lib/hipe -name "*.erl" | wc -l
        204
$ find lib/hipe -name "*.erl" | xargs grep '^-compile(export_all)' | wc -l
        0



Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

Mats Cronqvist (ÄL2/EAB)


Kostis Sagonas wrote:

> Being somebody who never used the -compile(export_all) directive
> in his life, I really would very much like to understand why this
> proposed addition would be "immensely useful" especially since
> currently there are very nice alternatives:
>
> erlc +export_all File
> or
> c(File, [export_all]).
>
> which nicely do the trick (whenever *really* needed).

   perhaps in an environment where you cannot use erlc? perhaps because there
are 27 include files in places known only to the makefile, or the source code is
not available? purely hypothetical of course.

    mats


Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

chandru
In reply to this post by Kostis Sagonas-3
On 2 Mar 2005, at 14:40, Kostis Sagonas wrote:

> Chandrashekhar Mullaparthi wrote:
>
>> Me too! I've tried wrapping the -compile(export_all) directive in
>> -ifdef(debug)/-endif and then use a Makefile to compile with the debug
>> option or not. But then I can't deliver this system to test as it is
>> not what will go live. So this feature would be immensely useful.
>
> Being somebody who never used the -compile(export_all) directive
> in his life, I really would very much like to understand why this
> proposed addition would be "immensely useful" especially since
> currently there are very nice alternatives:
>
> erlc +export_all File
> or
> c(File, [export_all]).
>
> which nicely do the trick (whenever *really* needed).
>

Neither the compiler nor the source code is included in any(almost -
except when we use yaws) system we produce. Our test team don't like us
changing modules in the test installation (understandably) - so
troubleshooting becomes a bit of a hassle. Typically, this is what I
have to do if I want to troubleshoot in the testplant.

1. Take a backup of the existing module
2. Compile correct version of module with +export_all option
3. FTP to testplant (sometimes via two hops because security folks are
sometimes Business Prevention Officers)
4. Load new module
5. Do stuff
6. Backout the patch

It'll be nice to be able to just do this.

5. Do stuff.


>> I'm afraid of removing the export_all from a module.
>
> Hint: don't add it in the first place.

Well, when there are 15 different services live and 40 erlang nodes to
support each with different versions of software, it is easier said
than done.

cheers
Chandru



Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

Luke Gorrie-3
In reply to this post by Kostis Sagonas-3
Kostis Sagonas <kostis> writes:

> currently there are very nice alternatives:
>
> erlc +export_all File
> or
> c(File, [export_all]).

even on my development machine it would be more like this:

  "Touch" the file (e.g. insert blank line, save, undo, save.)
  'make debug'
  Reload the right module
  ... do what I want ...
  "Touch" the file again
  'make'
  Reload the right module

And more complicated if the code is running on a target machine or the
source file I have is hacked/broken.

In practice I've found this way too inconvenient even when it comes to
adding +debug_info to run the debugger and I do that /way/ less than
poking at internal functions.

Thankfully the +debug_info problem is solved once-and-for-all with a
line in ~/.bashrc:

    export ERL_COMPILER_OPTIONS='[debug_info]'

too dangerous to do the export_all equivalent though :-)




Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

James Hague-5
Does the compiler not take advantage of functions being internal to a
module?  For example, if a function always returns a tuple which is
immediately unpacked, then the tuple construction can be avoided and
the values returned in Erlang registers.  At least I recall reading
about this somewhere.

If this is the case, then you wouldn't be able to call internal
functions directly.


Reply | Threaded
Open this post in threaded view
|

Calling internal functions - foo::bar() ?

Björn Gustavsson-3
After some discussion in the OTP group, we have decided NOT
to implement any support for calling a local function.

The reason is that it could prevent us from implementing
(or drastically complicate) future optimizations in the compiler.

(We haven't implemented the kind of optimization mentioned below,
but we hope to do it in a future release.)

/Bjorn

James Hague <james.hague> writes:

> Does the compiler not take advantage of functions being internal to a
> module?  For example, if a function always returns a tuple which is
> immediately unpacked, then the tuple construction can be avoided and
> the values returned in Erlang registers.  At least I recall reading
> about this somewhere.
>
> If this is the case, then you wouldn't be able to call internal
> functions directly.
>

--
Bj?rn Gustavsson, Erlang/OTP, Ericsson AB


Reply | Threaded
Open this post in threaded view
|

Debunking The Expensive Exported-Function Call Myth

Luke Gorrie-3
Bjorn Gustavsson <bjorn> writes:

> After some discussion in the OTP group, we have decided NOT
> to implement any support for calling a local function.

Fair enough.

> James Hague <james.hague> writes:
>
> > Does the compiler not take advantage of functions being internal to a
> > module?  For example, if a function always returns a tuple which is
> > immediately unpacked, then the tuple construction can be avoided and
> > the values returned in Erlang registers.  At least I recall reading
> > about this somewhere.
> >
> > If this is the case, then you wouldn't be able to call internal
> > functions directly.

This one seems easy. Suppose you have this code:

  foo() -> {A, B} = bar(), ...code...
  bar() -> {1, 2}.

then the optimized version (using Core Erlang syntax for
<Multiple,Values> in registers syntax) is something like:

  foo() -> <A, B> = bar(), ...code...
  bar() -> <1, 2>.

then to support calling bar/0 externally you'd need a tiny little
wrapper that calls the optimized one and packs the result into a
tuple:

  foo() -> <A, B> = opt(), ...code...
  opt() -> <1, 2>.
  bar() -> <A, B> = opt(), {A, B}.

This way the optimization would also benefit people using export_all.
Note: That includes everyone using embedded yaws. :-)




Reply | Threaded
Open this post in threaded view
|

Debunking The Expensive Exported-Function Call Myth

James Hague-5
On 09 Mar 2005 17:51:29 +0100, Luke Gorrie <luke> wrote:
>
> then the optimized version (using Core Erlang syntax for
> <Multiple,Values> in registers syntax) is something like:
>
>   foo() -> <A, B> = bar(), ...code...
>   bar() -> <1, 2>.

Very cool!  I did not know about that!

I think I erred in providing the easiest possible example to shoot down :)

An alternate example is that you could determine the return type of a
local function via "type discovery," then propagate that information
to the calling function.  That is, if you knew a local function always
returned a list, then specialized code could be used to process that
value after it is returned.

James