[erlang-questions] How to get the line number of current executable code?

52 views
Skip to first unread message

devdoer bird

unread,
Aug 15, 2008, 1:03:08 PM8/15/08
to erlang-q...@erlang.org
HI:
 
I want to implement a function like "get_current_lineno()/0" to get the current line number of the calling point?
Eg.
.....
....
io:format("current line is ~w\n",[get_current_lineno()])
.....
 
the above code will print the line number of the calling point in the source file.
 
How can I do this  in erlang?

Anders Nygren

unread,
Aug 15, 2008, 2:22:54 PM8/15/08
to devdoer bird, erlang-q...@erlang.org
2008/8/15 devdoer bird <devd...@gmail.com>:

There is a predefined macro ?LINE that does that
so
io:format("current line is ~w\n",[?LINE])

/Anders

> _______________________________________________
> erlang-questions mailing list
> erlang-q...@erlang.org
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
_______________________________________________
erlang-questions mailing list
erlang-q...@erlang.org
http://www.erlang.org/mailman/listinfo/erlang-questions

devdoer bird

unread,
Aug 15, 2008, 2:31:42 PM8/15/08
to Anders Nygren, erlang-q...@erlang.org
Thanks.
 
How can I do this without macro? I know python supply some tools to determine the line number in run time,like inspect module.

 
2008/8/16, Anders Nygren <anders...@gmail.com>:

Richard Carlsson

unread,
Aug 15, 2008, 3:05:08 PM8/15/08
to devdoer bird, erlang-q...@erlang.org
devdoer bird wrote:
> How can I do this without macro? I know python supply some tools to
> determine the line number in run time,like inspect module.

There is currently no support for that in Erlang.

/Richard

Matt Williamson

unread,
Aug 15, 2008, 3:07:49 PM8/15/08
to devdoer bird, erlang-questions
You should trust the macro. It must use a similar method to Python's because they are both compiled to bytecode and thus there wouldn't *really* be line numbers in either one.

2008/8/15 devdoer bird <devd...@gmail.com>

Edwin Fine

unread,
Aug 15, 2008, 4:29:50 PM8/15/08
to Matt Williamson, erlang-questions
Something I've wished for in numerous languages over the years is a macro that expands to the current function, something like ?MODULE. I don't suppose there is one lurking somewhere in Erlang...?

2008/8/15 Matt Williamson <dawsd...@gmail.com>



--
For every expert there is an equal and opposite expert - Arthur C. Clarke

Ulf Wiger

unread,
Aug 15, 2008, 5:06:56 PM8/15/08
to Edwin Fine, erlang-questions
Why sure, you just do this:

-module(m).
-export([f/0]).

-define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).

f() ->
{current_function, ?FUNCTION}.

Eshell V5.5.4 (abort with ^G)
1> c(m).
{ok,m}
2> m:f().
{current_function,{m,f,0}}
3>

BR,
Ulf W ;-)

2008/8/15 Edwin Fine <erlang-ques...@usa.net>:

Edwin Fine

unread,
Aug 15, 2008, 5:48:27 PM8/15/08
to Ulf Wiger, erlang-questions
How cool is that?! Thanks!

Ahmed Ali

unread,
Aug 16, 2008, 12:40:08 PM8/16/08
to Richard Carlsson, erlang-q...@erlang.org
Hi Richard,

How about if I compiled the source with debugging enabled? Isn't this
information supposed to be there (along with function name and other
info)?

/Ahmed Al-Issaei

Edwin Fine

unread,
Aug 16, 2008, 1:59:08 PM8/16/08
to Ulf Wiger, erlang-questions
Ulf,

On second thoughts, although that IS very cool, it would likely be very expensive because it generates and catches an exception. This would matter if it is used to do a lot of logging (which is what I would use it for). What I really would like is a compile-time constant (pre-processor macro). I suppose one could hack epp...?

Ed

On Fri, Aug 15, 2008 at 5:06 PM, Ulf Wiger <u...@wiger.net> wrote:

Richard Carlsson

unread,
Aug 16, 2008, 2:19:12 PM8/16/08
to Ahmed Ali, erlang-q...@erlang.org
Ahmed Ali wrote:
> Hi Richard,
>
> How about if I compiled the source with debugging enabled? Isn't this
> information supposed to be there (along with function name and other
> info)?

The problem is that there is no direct line-for-line mapping between the
abstract code in the debugging information, and the executing beam code.
The beam code does contain the info about the current function, but no
line numbers. Using a combination of the two, you could find the line
number for the current function, but figuring out the actual line
within that function (given the current point in the beam code) could
only be approximated using heuristics.

If you're actually running in interpreted mode (debugging mode), you
do get the current line, but it's a couple of orders of magmitude
slower, so you don't want to do that for all your code.

I hope some day someone will find the time to make the compiler
propagate the line number information into a mapping table that could
be included in the beam file at all times, even if the file was not
compiled with debugging enabled. That would make it possible to give
much nicer stacktraces.

Richard Carlsson

unread,
Aug 16, 2008, 2:22:22 PM8/16/08
to Edwin Fine, erlang-questions
Edwin Fine wrote:
> On second thoughts, although that IS very cool, it would likely be very
> expensive because it generates and catches an exception. This would
> matter if it is used to do a lot of logging (which is what I would use
> it for). What I really would like is a compile-time constant
> (pre-processor macro). I suppose one could hack epp...?

Don't worry about that. Exception handling is not particularly
expensive in Erlang. (Certainly not compared to the work of logging.)

/Richard

Howard Yeh

unread,
Aug 16, 2008, 3:41:01 PM8/16/08
to erlang-q...@erlang.org
On 8/16/08, Richard Carlsson <rich...@it.uu.se> wrote:

> If you're actually running in interpreted mode (debugging mode), you
> do get the current line, but it's a couple of orders of magmitude
> slower, so you don't want to do that for all your code.


How do I run the vm in debugging mode?

In the AST transformation code for my pet lisp frontend, it's often
hard to tell where a pattern match failed, b/c there can be many
matches within a single function.

It would be /very/ helpful if running in debugging mode gives me the
line #. I can live with performance penalty at development time...

Kevin Scaldeferri

unread,
Aug 15, 2008, 4:35:45 PM8/15/08
to Matt Williamson, erlang-questions
Many languages are compiled to byte code, but able to recover line
numbers at run time. I assume they annotate the byte codes with file
and line information. Note that this is more powerful than the Erlang
macros. For example, Perl's caller() function allows you to inspect
the full call stack in this way.


-kevin

Richard Carlsson

unread,
Aug 17, 2008, 4:37:10 AM8/17/08
to Howard Yeh, erlang-q...@erlang.org
Howard Yeh wrote:
> How do I run the vm in debugging mode?

Not the vm as such, more like a meta-interpreter:

http://www.erlang.org/doc/apps/debugger/index.html

/Richard

Ulf Wiger

unread,
Aug 17, 2008, 5:19:44 AM8/17/08
to Edwin Fine, erlang-questions
I should perhaps bring special notation to the smiley at the
end of my message. (:

Whether or not the solution is cool is surely a matter of
taste - but I believe that the one who first came up with it
was Mats Cronqvist, the champion of obfuscated Erlang
code. (:

I'm not sure about *very* expensive. The exception mechanism
isn't that heavyweight. At least in the past, there were issues
with HiPE, in that exceptions in native code would generate an
empty stack trace. I vaguely recall that being fixed now.

I agree that a compile-time constant would be much preferred.

BR,
Ulf W

2008/8/16 Edwin Fine <erlang-ques...@usa.net>:

Thomas Lindgren

unread,
Aug 17, 2008, 6:01:32 AM8/17/08
to erlang-questions


--- On Sat, 8/16/08, Edwin Fine <erlang-ques...@usa.net> wrote:


> On second thoughts, although that IS very cool, it would
> likely be very
> expensive because it generates and catches an exception.
> This would matter
> if it is used to do a lot of logging (which is what I would
> use it for).
> What I really would like is a compile-time constant
> (pre-processor macro). I
> suppose one could hack epp...?

The basic problem is that epp works on the token level, not the syntax tree level, so when you find ?FUNCTION there is no information about what function you're in. (And figuring it out seems like a thankless job.)

One possible hack: expand ?FUNCTION into something that can be recognized and replaced by a later pass. For instance:

1. In epp, replace ?FUNCTION by the syntax tree or tokens of a call to a made-up function, "erlang:current_function()", or some other unique well-known marker.

2. In sys_pre_expand, walk the syntax tree for each function M:F/N, and replace all occurrences of "erlang:current_function()" with {M, F, N}. (As part of expanding away records, etc.)

Occurrences of ?FUNCTION outside of functions will have to be handled too, e.g. by an error.

Best,
Thomas

Thomas Lindgren

unread,
Aug 17, 2008, 5:51:37 AM8/17/08
to erlang-q...@erlang.org


--- On Sat, 8/16/08, Howard Yeh <hay...@gmail.com> wrote:
> In the AST transformation code for my pet lisp frontend,
> it's often
> hard to tell where a pattern match failed, b/c there can
> be many
> matches within a single function.
>
> It would be /very/ helpful if running in debugging mode
> gives me the
> line #. I can live with performance penalty at development
> time...

I'm not sure if this helps in your case, but if you're satisfied with getting line numbers in your exceptions, try smart_exceptions from jungerl. It's a parse transform, so it works without the debugger.

Best,
Thomas

Thomas Lindgren

unread,
Aug 17, 2008, 8:14:24 AM8/17/08
to erlang-q...@erlang.org

--- On Sat, 8/16/08, Richard Carlsson <rich...@it.uu.se> wrote:
> I hope some day someone will find the time to make the
> compiler
> propagate the line number information into a mapping table
> that could
> be included in the beam file at all times, even if the file
> was not
> compiled with debugging enabled. That would make it
> possible to give
> much nicer stacktraces.

Indeed. Doing this might be a bit finicky but it's very helpful. The usual scripting language suspects already provide such stack traces, by the way.

Best,
Thomas

Howard Yeh

unread,
Aug 17, 2008, 1:25:11 PM8/17/08
to thomasl...@yahoo.com, erlang-q...@erlang.org
On 8/17/08, Thomas Lindgren <thomasl...@yahoo.com> wrote:
>
> I'm not sure if this helps in your case, but if you're satisfied with getting line numbers in your exceptions, try smart_exceptions from jungerl. It's a parse transform, so it works without the debugger.
>

Ah, thanks for the pointer.

So you are basically providing a fall through case for M-F-A-line
error report whenever there's branching? It sounds like a good way to
do it.

I've read somebody (Joe?) saying that pattern matchings in erlang are
like mini contracts. Early failure from failed match is a good thing.
So I am wondering if Thomas's code transfomer is compatible with the
Erlang philosophy (I think it is). But I may be missing the obvious.

As mentioned, I am playing around with my pet lisp frontend. Having
seem Thomas's smart exception, it seems that it makes sense to provide
special syntatic support for matching failure. Something like,

(case X
<cases>*
: "expected such and such input")

The last line is a syntatic sugar for a universal pattern that throws
a {badmatch...}, but with M-F-A/line and reason. Ditto with function
clauses et al.

Robert V. probably wouldn't like it : )

Thomas Lindgren

unread,
Aug 17, 2008, 3:48:18 PM8/17/08
to erlang-q...@erlang.org

--- On Sun, 8/17/08, Howard Yeh <hay...@gmail.com> wrote:
> So you are basically providing a fall through case for
> M-F-A-line
> error report whenever there's branching? It sounds like
> a good way to
> do it.

Basically the transform tries to "elaborate" all the places where an exception can be thrown into providing more information, and the program then throws the new exception when it's encountered. (There are a few cases where the transform misses out: undefined function calls and, I seem to recall, exceptions when building binaries, at the very least.)

> I've read somebody (Joe?) saying that pattern matchings
> in erlang are
> like mini contracts. Early failure from failed match is a
> good thing.
> So I am wondering if Thomas's code transfomer is
> compatible with the
> Erlang philosophy (I think it is). But I may be missing the
> obvious.

All that basic smart_exceptions does is provide more information about the causes of an exception, so I don't think it's incompatible with such a principle. ("The basic transform", you ask? In principle, smart_exceptions also permits you to insert and run arbitrary code at the point of an exception, a bit like Common Lisp's condition handlers. But that's not tested much, and probably a bit too much complication.)

Best,
Thomas

Richard A. O'Keefe

unread,
Aug 17, 2008, 7:58:11 PM8/17/08
to thomasl...@yahoo.com, erlang-questions
On 17 Aug 2008, at 10:01 pm, Thomas Lindgren wrote:
> The basic problem is that epp works on the token level, not the
> syntax tree level, so when you find ?FUNCTION there is no
> information about what function you're in. (And figuring it out
> seems like a thankless job.)
>
I note that while __FILE__, __LINE__, __DATE__, __TIME__ and so on are
macros in C, __func__ is not. It is a keyword. So the solution that
Thomas Lindgren proposes seems good. I would prefer one mechanism that
solves several issues, so I suggest that instead of ?FUNCTION the thing
to have is ?LOCATION
=> {File, Line, Module, Function, Arity, Clause_Number}

Richard A. O'Keefe

unread,
Aug 17, 2008, 8:46:15 PM8/17/08
to Kevin Scaldeferri, erlang-questions

On 16 Aug 2008, at 8:35 am, Kevin Scaldeferri wrote:

> Many languages are compiled to byte code, but able to recover line
> numbers at run time. I assume they annotate the byte codes with file
> and line information. Note that this is more powerful than the Erlang
> macros. For example, Perl's caller() function allows you to inspect
> the full call stack in this way.

There is a tradeoff.
When your compiler does good stuff like constant propagation,
inlining, loop unrolling, loop fusion, &c, it gets hard to make
'the line number' mean anything. For example, suppose we had

Ns = [sum(L) || L <- Ls],
Ds = [length(L) || L <- Ls],
Aves = [N/D || {N,D} <- lists:zip(Ns, Ds)]

This is the kind of thing the GHC compiler eats for lunch;
assuming Ns and Ds are not used anywhere else it turns into
the equivalent of

Aves = [sum(L)/length(L) || L <- Ls]

Which line does this correspond to? ALL of them.
(Actually, I believe GHC will take this a stage further, and inline
and fuse the sum and length loops as well. In which case we have
code within a single "line" coming from several files.)

The Erlang compiler isn't that smart. (Yet. A man can dream.)

One of the reasons that Perl can give you line numbers is that
Perl is to speed what a spent match is to illumination.

Debugging information can be bulky.
For a non-Erlang example, I tried a small Java file.
It has 172 lines, 116 of which count as SLOC.
javac -g:none Calls.java => 2583 bytes
javac Calls.java => 3035 bytes; 452 bytes of line#
javac -g Calls.java => 3283 bytes; 248 bytes of other stuff
The Java compiler counted 96 lines it thought worth recording,
so that's 4.71 bytes per line. (Clearly they are not bothering
to compress this much.) There are about 1380 bytes of actual code,
so the line number table is about 1/3 as big as the code.

Even assuming that virtual memory is huge and close to free,
line number information should be used rarely enough that you
don't want to mix it in with the instructions; you want to
segregate it somewhere else.

The really interesting thing is that javap basically lists the
line number mappings backwards. Instead of saying "block [a..z)
of byte code corresponds to line L", it says "line L corresponds
to byte code starting at x". This suggests a fairly, um,
direct mapping from source code to byte code: inlining,
loop fusion, loop unrolling, &c are left to the JIT.

Now the Erlang compiler isn't as smart as GHC, but it _is_
smarter than that. With inlining and tail recursion optimisation,
even the stack trace isn't what it seems.

A rather long-winded way of saying TANSTAAFL, I suppose.

Robert Virding

unread,
Aug 18, 2008, 8:59:18 AM8/18/08
to Richard A. O'Keefe, erlang-questions
2008/8/18 Richard A. O'Keefe <o...@cs.otago.ac.nz>

On 16 Aug 2008, at 8:35 am, Kevin Scaldeferri wrote:

There is a tradeoff.
When your compiler does good stuff like constant propagation,
inlining, loop unrolling, loop fusion, &c, it gets hard to make
'the line number' mean anything.  For example, suppose we had

       Ns = [sum(L) || L <- Ls],
       Ds = [length(L) || L <- Ls],
       Aves = [N/D || {N,D} <- lists:zip(Ns, Ds)]

This is the kind of thing the GHC compiler eats for lunch;
assuming Ns and Ds are not used anywhere else it turns into
the equivalent of

       Aves = [sum(L)/length(L) || L <- Ls]

Which line does this correspond to?  ALL of them.
(Actually, I believe GHC will take this a stage further, and inline
and fuse the sum and length loops as well.  In which case we have
code within a single "line" coming from several files.)

The Erlang compiler isn't that smart.  (Yet.  A man can dream.)

One problem Erlang would have doing this type of optimisation, which would be wonderful to have, is the handling of side effects and errors. That type of aggressive inlining and fusing would change the order in which side effects occur which means that the code would not be equivalent. Similar for errors. Haskell, being side-effect free, does not have this problem.

Robert

Andras Georgy Bekes

unread,
Aug 18, 2008, 10:00:35 AM8/18/08
to erlang-q...@erlang.org
> -define(FUNCTION, hd(element(2,element(2,catch erlang:error([]))))).
A safer solution (it has no side effects, unlike the above):

-define(FUNCTION,element(2,process_info(self(),current_function))).

I don't know if it's more expensive or not, but if it does matter,
you're doing something wrong.

Georgy

Richard A. O'Keefe

unread,
Aug 18, 2008, 8:53:23 PM8/18/08
to Robert Virding, erlang-questions

On 19 Aug 2008, at 12:59 am, Robert Virding wrote:

> The Erlang compiler isn't that smart. (Yet. A man can dream.)
>
> One problem Erlang would have doing this type of optimisation, which
> would be wonderful to have, is the handling of side effects and
> errors.

I have also dreamed of a
-pure([f/n,...]).
directive, such as NU Prolog had.
This would make a verifiable claim that the function(s) named would
only call functions that are themselves pure, and a promise that if
any exception would be raised in a call to such a function it would
not matter which exception.

However, that seemed off topic.

--
If stupidity were a crime, who'd 'scape hanging?

Andras Georgy Bekes

unread,
Aug 19, 2008, 11:39:22 AM8/19/08
to erlang-q...@erlang.org
> -pure([f/n,...]).
> directive, such as NU Prolog had.
> This would make a verifiable claim that the function(s) named would
> only call functions that are themselves pure
What happens if a pure function calls a function that is not pure?

I mean, the compiler just can't check it. Of course it can check local
functions, but a function in another module can not be trusted. It
might be pure at the time of compilation, but it might be impure in its
next version.

It could only be checked in runtime, throwing an exception whenever an
impure function is called from a pure one.

Georgy

Ulf Wiger (TN/EAB)

unread,
Aug 19, 2008, 12:59:47 PM8/19/08
to Andras Georgy Bekes, erlang-q...@erlang.org
Andras Georgy Bekes skrev:

>> -pure([f/n,...]).
>> directive, such as NU Prolog had.
>> This would make a verifiable claim that the function(s) named would
>> only call functions that are themselves pure
> What happens if a pure function calls a function that is not pure?
>
> I mean, the compiler just can't check it. Of course it can check local
> functions, but a function in another module can not be trusted. It
> might be pure at the time of compilation, but it might be impure in its
> next version.

Yes, so cross-module calls cannot be allowed in a pure function,
at least unless we find a way to statically group modules together.

BR,
Ulf W

David Mercer

unread,
Aug 19, 2008, 2:30:26 PM8/19/08
to Richard A. O'Keefe, erlang-questions
Richard A. O'Keefe wrote:
>
> I have also dreamed of a
> -pure([f/n,...]).
> directive, such as NU Prolog had.
> This would make a verifiable claim that the function(s) named would
> only call functions that are themselves pure, and a promise that if
> any exception would be raised in a call to such a function it would
> not matter which exception.

For those of us not well-versed in NU Prolog, what is the benefit of this?
Please advise. Thank-you.

David

Kevin Scaldeferri

unread,
Aug 19, 2008, 2:50:12 PM8/19/08
to dme...@alum.mit.edu, erlang-questions

On Aug 19, 2008, at 11:30 AM, David Mercer wrote:

> Richard A. O'Keefe wrote:
>>
>> I have also dreamed of a
>> -pure([f/n,...]).
>> directive, such as NU Prolog had.
>> This would make a verifiable claim that the function(s) named would
>> only call functions that are themselves pure, and a promise that if
>> any exception would be raised in a call to such a function it would
>> not matter which exception.
>
> For those of us not well-versed in NU Prolog, what is the benefit of
> this?
> Please advise. Thank-you.


The compiler can perform optimizations which might otherwise not be
possible. For example, various sorts of loop fusion optimizations are
provably safe for pure functions.


-kevin

Richard A. O'Keefe

unread,
Aug 20, 2008, 1:44:33 AM8/20/08
to Andras Georgy Bekes, erlang-q...@erlang.org

On 20 Aug 2008, at 3:39 am, Andras Georgy Bekes wrote:

>> -pure([f/n,...]).
>> directive, such as NU Prolog had.
>> This would make a verifiable claim that the function(s) named would
>> only call functions that are themselves pure
> What happens if a pure function calls a function that is not pure?
>
> I mean, the compiler just can't check it.

Yes it can. That's the whole POINT of -pure declarations.
The NU Prolog system *could* and *did* check this.

> Of course it can check local
> functions, but a function in another module can not be trusted.

Cannot be trusted? Sure it can. You haven't seen a complete
proposal, because I have other maddened grizzly bears to stun,
but the idea is that
- the meta-data for a module records which exported functions are
pure and which are not
- when the compiler notes a pure function calling a function
from another module, it records a dependency on that function
being exported as pure
- when a module is loaded, the run time system checks that
every function it tries to import as pure from some other
module IS pure if that module is already loaded,
every module that depends on this one exporting some
function(s) as pure is satisfied.
If either check fails, the module is not loaded.

This takes care of the "another module" issue.
The tricky one is higher order functions.
I actually came up with this idea back shortly before
'funs' were added to the language, and dropped it when they
came in. There are basically two ways out: one is to say
that a pure function can't be or call a higher order function,
and the other is to use some sort of type system.

Richard A. O'Keefe

unread,
Aug 20, 2008, 1:59:49 AM8/20/08
to dme...@alum.mit.edu, erlang-questions
On 20 Aug 2008, at 6:30 am, David Mercer wrote:
> For those of us not well-versed in NU Prolog, what is the benefit of
[-pure]
> this?


This was implicit in the original context:
"Haskell can do heavy duty optimisation that Erlang can't".
"Yes, but Haskell is pure, and Erlang isn't."
"Yes, but with functions declared to be -pure, Erlang
could do better than it does."

Andras Georgy Bekes

unread,
Aug 21, 2008, 6:16:23 AM8/21/08
to erlang-q...@erlang.org
> - the meta-data for a module records which exported functions are
> pure and which are not
> - when the compiler notes a pure function calling a function
> from another module, it records a dependency on that function
> being exported as pure
> - when a module is loaded, the run time system checks that
> every function it tries to import as pure from some other
> module IS pure if that module is already loaded,
> every module that depends on this one exporting some
> function(s) as pure is satisfied.
> If either check fails, the module is not loaded.
This is completely against current Erlang practice.

Currently if a module A uses module B, noone checks if B contains the
used functions or not. Neither at compile time, nor at module load
time. I think because the check would make module upgrades way more
difficult.

Think about a module B using a function AF from module A. In the next
version of the modules, the function A:AF is removed and B is not using
it any more. Currently you just load the two modules. In the presence
of a load-time check, you'd have to load module B first, then A. No
problem here.

Now think about a module A using B's BF and B using A's AF. When both
functions are removed, there is no legal upgrade order.

The same problem exists with checked pure functions. Module A using B's
pure BF (and expects it to be pure), and B using A's pure AF (and
expects it to be pure). In the next version both the functions switch
to impure, together with their consumers. There is no legal upgrade
order :-(

There probably are solutions (simultaneous atomic loading of several
modules? using extra transition module versions to make the upgrade
possible?), but current module upgrading technology/practice must
change radically.

Georgy

Richard A. O'Keefe

unread,
Aug 22, 2008, 12:34:08 AM8/22/08
to Andras Georgy Bekes, erlang-q...@erlang.org

On 21 Aug 2008, at 10:16 pm, Andras Georgy Bekes wrote:

>> - the meta-data for a module records which exported functions are
>> pure and which are not
>> - when the compiler notes a pure function calling a function
>> from another module, it records a dependency on that function
>> being exported as pure
>> - when a module is loaded, the run time system checks that
>> every function it tries to import as pure from some other
>> module IS pure if that module is already loaded,
>> every module that depends on this one exporting some
>> function(s) as pure is satisfied.
>> If either check fails, the module is not loaded.

> This is completely against current Erlang practice.

(a) That's a very misleading way to put it.

It would only be "against" if it in some way opposed or prevented
the kinds of things people are doing.

Erlang *happens* not to check very much, but this is hardly a
core design principle.

(b) IT DOESN'T MATTER!
For heaven's sake, I was answering a question about an idea I had
more than ten years ago, which was abandoned when Erlang got
'funs'.

>
> Currently if a module A uses module B, noone checks if B contains the
> used functions or not. Neither at compile time, nor at module load
> time. I think because the check would make module upgrades way more
> difficult.

First off, you can't do it at compile time because you do not know
*which* module called B, or which version of that module, A will
eventually
be loaded with. That's why it needs to be a load time conversion.

Second, haven't we all heard enough about "Version Skew" and "DLL Hell"
over the last N years to convince us that making it as easy as possible
for people to shoot themselves in the foot is not always a Good Thing?

If you have two loaded modules, A and B, and A uses something that B
provides, and you replace B with a B' that does not provide that any
more, what you have done is NOT an upgrade. What you have done is to
convert a working system into a non-working system. If you have a
new A' that doesn't need that service from B', then either you need
to change A to A' first, or you need to replace both modules *together*.


Just at the moment I am vey hot under the collar about "upgrades".
Here's my story:

I have a Macintosh on my desk.

I have to teach 5 introductory programming lectures to
first year surveyors. The surveying department insisted
on Visual Basic as the programming language. Since their
students will mostly be making minor additions to Excel
spreadsheets, this almost makes sense.

Fortunately, Excel is part of Microsoft Office for the Mac,
and last year I was able to develop examples using VBA in
Excel on my Mac.

This year the system administrators installed Microsoft
Office 2008 for Macintosh on my machine.

It wasn't until I tried revising my materials for SURV112
that I discovered that Office 2008 does not include VBA
any more. Gone. Vanished. All Office 2008 can do with
VBA macros is offer to delete them. We're supposed to
use AppleScript instead.

I've taken the trouble to learn AppleScript, and it is
certainly integrated with MacOS in a way that VBA never
was.

None-the-less, I am ***HOPPING MAD*** that nobody told
me when the "upgrade" was done "Oh, by the way, this is
going to remove a feature you need for your work; do
you really want it?"

If my configuration is inconsistent, I d--n well *WANT* to be
told about it before the damage is done.

I am not arguing against hot loading.
What I don't like is *silently* moving to an inconsistent state
or a state where functionality I rely on is missing.

(I've also lost the ability to print slides, because Acrobat 8
has this weird bug where slide pages after the first are mirror-
imaged, and the sysadmins were terrified at the thought of the
trouble they've have trying to replace it with an older version.
Hopefully Acrobat 9, which they've now installed, fixes this...)

>
> Now think about a module A using B's BF and B using A's AF. When both
> functions are removed, there is no legal upgrade order.

Yes there is. It's A+B *together.
I am not saying that this is supported *now*,
but it could be, and it should be.
And for the "block compilation" that people keep mentioning,
it will *have* to be, for this very reason.

You see, when you say "there is no legal upgrade order",
what that *really* means is that "if you replace modules one
at a time, there can be unavoidable windows when the system
is in an inconsistent state, does not know that, and tries
to continue operations anyway." Does that sound like a good idea?


Anyrate, to repeat: this was *NOT* a current proposal,
otherwise it would have been an EEP, not an off-hand remark
in another thread, so it was pointless to criticise it.

Raimo Niskanen

unread,
Aug 22, 2008, 3:24:48 AM8/22/08
to erlang-q...@erlang.org
On Fri, Aug 22, 2008 at 04:34:08PM +1200, Richard A. O'Keefe wrote:
>
> On 21 Aug 2008, at 10:16 pm, Andras Georgy Bekes wrote:
>
>
: :

> >
> > Now think about a module A using B's BF and B using A's AF. When both
> > functions are removed, there is no legal upgrade order.
>
> Yes there is. It's A+B *together.
> I am not saying that this is supported *now*,
> but it could be, and it should be.
> And for the "block compilation" that people keep mentioning,
> it will *have* to be, for this very reason.
>
> You see, when you say "there is no legal upgrade order",
> what that *really* means is that "if you replace modules one
> at a time, there can be unavoidable windows when the system
> is in an inconsistent state, does not know that, and tries
> to continue operations anyway." Does that sound like a good idea?

I just want to point out, for the record, that the problem
is not completely unsolvable today. This is what the
OTP Release Handler does.

If you build your system using OTP mechanisms (gen_servers,
supervision trees, etc...) the release handler pauses
all processes (in their gen_servers) before upgrading all
modules belonging to an application, and then lets
them continue after the upgrade.

It is just not a language feature, and requires discipline.

>
>
:


--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB

Mats Cronqvist

unread,
Aug 25, 2008, 2:57:44 AM8/25/08
to Ulf Wiger, erlang-questions
Ulf Wiger wrote:
> I should perhaps bring special notation to the smiley at the
> end of my message. (:
>
> Whether or not the solution is cool is surely a matter of
> taste - but I believe that the one who first came up with it
> was Mats Cronqvist, the champion of obfuscated Erlang
> code. (:
>
thanks for the endorsement...

for the record, i have since moved on to using this:
-define(position,[process_info(self(),current_function),{line,?LINE}]).

sometimes adding this:
proplists:lookup(source,?MODULE:module_info(compile)).

mats

Ahmed Ali

unread,
Aug 25, 2008, 7:34:26 PM8/25/08
to Mats Cronqvist, erlang-questions
Hi All,

This discussion is interesting. Just wanted to know if it is possible
to get the function that called current function. Is this possible?

Best regards,

Ahmed Al-Issaei

Richard Carlsson

unread,
Aug 26, 2008, 2:58:08 AM8/26/08
to Ahmed Ali, erlang-questions
Ahmed Ali wrote:
> Hi All,
>
> This discussion is interesting. Just wanted to know if it is possible
> to get the function that called current function. Is this possible?

The only way of doing that is to force an exception, and then look
at the stack trace. Something like this:

Trace = try throw(oops) catch oops -> erlang:get_stacktrace() end

However, due to tail call optimization in Erlang, you will not see
any functions in the list that were visited on the way but were exited
through a tail call.

/Richard

Bengt Kleberg

unread,
Aug 26, 2008, 2:58:22 AM8/26/08
to erlang-questions
Greetings,

Building upon the suggestion made by Ulf Wiger this would probably work
(possible reasons for not working includes, but are not limited to, tail
calls):
-define(FUNCTION_THAT_CALLED, lists:nth(2, element(2,element(2,catch
erlang:error([]))))).


bengt

Mats Cronqvist

unread,
Aug 26, 2008, 4:54:50 AM8/26/08
to Richard Carlsson, erlang-questions
Richard Carlsson wrote:
> Ahmed Ali wrote:
>
>> Hi All,
>>
>> This discussion is interesting. Just wanted to know if it is possible
>> to get the function that called current function. Is this possible?
>>
>
> The only way of doing that is to force an exception, and then look
> at the stack trace.

there is no way to reliably get the name of the calling function.
it is true that the stack sometimes contain the name of the calling
function.
it is not true that the only way to inspect the stack is by forcing an
exception.

i'm too lazy to write actual code, but try this in the shell;

(r12@sterlett)41> {_,BT}=erlang:process_info(self(),backtrace).
(r12@sterlett)42> S=fun(B,{_,[_,{F,L}|_]})->
<<_:F/binary,R:L/binary,_/binary>> =B, R end.
(r12@sterlett)43> S(BT,re:run(BT,"Return addr\\s[0-9a-z]+\\s\\(([^\\s]*)")).
<<"erl_eval:expr/5">>

clear as the day!

mats

Richard Carlsson

unread,
Aug 26, 2008, 5:15:38 AM8/26/08
to Mats Cronqvist, erlang-questions
Mats Cronqvist wrote:
> it is not true that the only way to inspect the stack is by forcing an
> exception.
>
> i'm too lazy to write actual code, but try this in the shell;
>
> (r12@sterlett)41> {_,BT}=erlang:process_info(self(),backtrace).
> (r12@sterlett)42> S=fun(B,{_,[_,{F,L}|_]})->
> <<_:F/binary,R:L/binary,_/binary>> =B, R end.
> (r12@sterlett)43> S(BT,re:run(BT,"Return
> addr\\s[0-9a-z]+\\s\\(([^\\s]*)")).
> <<"erl_eval:expr/5">>

Ugh! I didn't know that flag to process_info existed, but I'm happy to
see that Mats' talent for sniffing out the dark corners of Erlang and
using them for unspeakable deeds is as strong as ever.

/Richard

Ahmed Ali

unread,
Aug 26, 2008, 3:05:10 PM8/26/08
to Mats Cronqvist, erlang-questions
Hi Mats,

I've seen process_display(Pid, backtrace) but never thought to use it
this way. Thanks for the insight.

Best regards,

Ahmed Al-Issaei

Reply all
Reply to author
Forward
0 new messages