Erlang: "extending" an existing module with new functions - erlang

I'm currently writing some functions that are related to lists that I could possibly be reused.
My question is:
Are there any conventions or best practices for organizing such functions?
To frame this question, I would ideally like to "extend" the existing lists module such that I'm calling my new function the following way: lists:my_funcion(). At the moment I have lists_extensions:my_function(). Is there anyway to do this?
I read about erlang packages and that they are essentially namespaces in Erlang. Is it possible to define a new namespace for Lists with new Lists functions?
Note that I'm not looking to fork and change the standard lists module, but to find a way to define new functions in a new module also called Lists, but avoid the consequent naming collisions by using some kind namespacing scheme.
Any advice or references would be appreciated.
Cheers.

To frame this question, I would ideally like to "extend" the existing lists module such that I'm calling my new function the following way: lists:my_funcion(). At the moment I have lists_extensions:my_function(). Is there anyway to do this?
No, so far as I know.
I read about erlang packages and that they are essentially namespaces in Erlang. Is it possible to define a new namespace for Lists with new Lists functions?
They are experimental and not generally used. You could have a module called lists in a different namespace, but you would have trouble calling functions from the standard module in this namespace.

I give you reasons why not to use lists:your_function() and instead use lists_extension:your_function():
Generally, the Erlang/OTP Design Guidelines state that each "Application" -- libraries are also an application -- contains modules. Now you can ask the system what application did introduce a specific module? This system would break when modules are fragmented.
However, I do understand why you would want a lists:your_function/N:
It's easier to use for the author of your_function, because he needs the your_function(...) a lot when working with []. When another Erlang programmer -- who knows the stdlb -- reads this code, he will not know what it does. This is confusing.
It looks more concise than lists_extension:your_function/N. That's a matter of taste.

I think this method would work on any distro:
You can make an application that automatically rewrites the core erlang modules of whichever distribution is running. Append your custom functions to the core modules and recompile them before compiling and running your own application that calls the custom functions. This doesn't require a custom distribution. Just some careful planning and use of the file tools and BIFs for compiling and loading.
* You want to make sure you don't append your functions every time. Once you rewrite the file, it will be permanent unless the user replaces the file later. Could use a check with module_info to confirm of your custom functions exist to decide if you need to run the extension writer.
Pseudo Example:
lists_funs() -> ["myFun() -> <<"things to do">>."].
extend_lists() ->
{ok, Io} = file:open(?LISTS_MODULE_PATH, [append]),
lists:foreach(fun(Fun) -> io:format(Io,"~s~n",[Fun]) end, lists_funs()),
file:close(Io),
c(?LISTS_MODULE_PATH).
* You may want to keep copies of the original modules to restore if the compiler fails that way you don't have to do anything heavy if you make a mistake in your list of functions and also use as source anytime you want to rewrite the module to extend it with more functions.
* You could use a list_extension module to keep all of the logic for your functions and just pass the functions to list in this function using funName(Args) -> lists_extension:funName(Args).
* You could also make an override system that searches for existing functions and rewrites them in a similar way but it is more complicated.
I'm sure there are plenty of ways to improve and optimize this method. I use something similar to update some of my own modules at runtime, so I don't see any reason it wouldn't work on core modules also.

i guess what you want to do is to have some of your functions accessible from the lists module. It is good that you would want to convert commonly used code into a library.
one way to do this is to test your functions well, and if their are fine, you copy the functions, paste them in the lists.erl module (WARNING: Ensure you do not overwrite existing functions, just paste at the end of the file). this file can be found in the path $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/src/lists.erl. Make sure that you add your functions among those exported in the lists module (in the -export([your_function/1,.....])), to make them accessible from other modules. Save the file.
Once you have done this, we need to recompile the lists module. You could use an EmakeFile. The contents of this file would be as follows:
{"src/*", [verbose,report,strict_record_tests,warn_obsolete_guard,{outdir, "ebin"}]}.
Copy that text into a file called EmakeFile. Put this file in the path: $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/EmakeFile.
Once this is done, go and open an erlang shell and let its pwd(), the current working directory be the path in which the EmakeFile is, i.e. $ERLANG_INSTALLATION_FOLDER/lib/stdlib-{$VERSION}/.
Call the function: make:all() in the shell and you will see that the module lists is recompiled. Close the shell.
Once you open a new erlang shell, and assuming you exported you functions in the lists module, they will be running the way you want, right in the lists module.
Erlang being open source allows us to add functionality, recompile and reload the libraries. This should do what you want, success.

Related

What is the recommended way to make & load a library?

I want to make a small "library" to be used by my future maxima scripts, but I am not quite sure on how to proceed (I use wxMaxima). Maxima's documentation covers the save(), load() and loadFile() functions, yet does not provide examples. Therefore, I am not sure whether I am using the proper/best way or not. My current solution, which is based on this post, stores my library in the *.lisp format.
As a simple example, let's say that my library defines the cosSin(x) function. I open a new session and define this function as
(%i0) cosSin(x) := cos(x) * sin(x);
I then save it to a lisp file located in the /tmp/ directory.
(%i1) save("/tmp/lib.lisp");
I then open a new instance of maxima and load the library
(%i0) loadfile("/tmp/lib.lisp");
The cosSin(x) is now defined and can be called
(%i1) cosSin(%pi/4)
(%o1) 1/2
However, I noticed that a substantial number of the libraries shipped with maxima are of *.mac format: the /usr/share/maxima/5.37.2/share/ directory contains 428 *.mac files and 516 *.lisp files. Is it a better format? How would I generate such files?
More generally, what are the different ways a library can be saved and loaded? What is the recommended approach?
Usually people put the functions they need in a file name something.mac and then load("something.mac"); loads the functions into Maxima.
A file can contain any number of functions. A file can load other files, so if you have somethingA.mac and somethingB.mac, then you can have another file that just says load("somethingA.mac"); load("somethingB.mac");.
One can also create Lisp files and load them too, but it is not required to write functions in Lisp.
Unless you are specifically interested in writing Lisp functions, my advice is to write your functions in the Maxima language and put them in a file, using an ordinary text editor. Also, I recommend that you don't use save to save the functions to a file as Lisp code; just type the functions into a file, as Maxima code, with a plain text editor.
Take a look at the files in share to get a feeling for how other people have gone about it. I am looking right now at share/contrib/ggf.mac and I see it has a lengthy comment header describing its purpose -- such comments are always a good idea.
For principiants, like me,
Menu Edit:configure:Startup commands
Copy all the functions you have verified in the first box (this will write your wxmaxima-init.mac in the location indicated below)
Restart Wxmaxima.
Now you can access the functions whitout any load() command

Why does Erlang have arity in its imports?

I find Erlang's module arity import /n where n is the number of arguments rather bizarre.
In Java and various other languages you can do something like:
import static com.stuff.Blah.myFunction;
Which will import all overloaded Blay.myFunction(..) regardless of parameters.
Besides I guess being explicit why did the language designers decide this was a good idea (I'm not trying to criticize the language... just curious)?
Does it have to do with code swapping?
Or does it have to do with hiding guard methods for recursion? If so why not allow arity on export but no need for arity on import?
Why would I want to be that explicit? That is import the two argument function but not the the three argument of myFunction?
You should be aware of what importing functions in Erlang really does. It is a pure textual transformation. If I do an -import(foo, [bar/1,baz/2]). it means that when I write a call like bar(5) or baz(a, 3) the compiler transforms these to foo:bar(5) and foo:baz(a, 3). That is all it does, nothing else. It doesn't check anything:
It doesn't check if the module foo contains the functions bar/1 or baz/2.
It doesn't even check if the module foo exists.
Really all it does is hide that you are calling a function in another module. That is why the recommendation from experienced Erlangers is "don't use it". It was a mistake. Unfortunately it is much easier to add stupid things than to get rid of them so we were never able to remove it.
"Does it have to do with code swapping?"
Yes, sort of. The unit of all code handling in Erlang is the module. So you compile modules, load modules, purge and delete modules. This means that there are no inter-module dependencies at all in the system and the compiler makes no assumptions about other modules when it is compiling a module. No assumptions are made that the environment in which a module is compiled will be the same in which it is run. That is why it is at runtime the system checks whether the function you are trying to call in another exists, or even if the module itself exists. That is why the import was a purely textual transformation.
Erlang was originally developed in Prolog.
In Prolog, the arity adds additional meaning to what you consider to be the 'arguments, as I understand from a function' in a procedural programming language. But that model does not apply here.
The so-called clauses 'married(X,Y).' and 'married(X,Y,Z).' imply a different kind of relationship 'married', which can be declared as married/2 and married/3.
In procedural programming, 'add(a,b)' or 'add(a,b,c)' are intended to generate the addition of a different number of arguments. That's not immediately the case in Prolog, where it is possible to have the relationship 'a and b, added' or 'a, b and c, added' mean something else. Needless to say, Prolog allows you to declare 'add' as you would expect a function would do. But it allows for more. More available meaning, means more need to control it.
And as in any module system, selecting what you want to expose to external clients makes sense: hence the declaration of arity.
Does it have to do with code swapping?
Kind of. The modules in Erlang are compiled separately (which is part of what allows code swapping), unlike Java classes, so the compiler doesn't know how many versions of the imported function with different arities exist. It could assume that all calls of a function with the given name come from the same module, of course, but the designers likely decided it wasn't particularly useful.
In fact, you rarely want to use imports at all, at least in my experience, just as you rarely use static imports in Java. Just write module:function, like Class.staticMethod.
Or does it have to do with hiding guard methods for recursion?
No, since not importing functions doesn't hide them in any way.

Including an external application in ZF2

I'm trying to use phpBB3 (forum app) along with ZF2. For that, I have to include a file from the phpBB3. In theory this is as simple as:
include('/path/to/phpbb3/common.php');
$user->session_begin(); //$user is defined in common.php file
In common.php a lot of globals are defined, and after that are required some files which are using those globals.
In ZF2 simply including the common.php would not work, because the scope of the globals will not span over the required files, so I tried a little trick:
//in Application/Forum/Service
public function callForumAPI(){
$zf_dir = getcwd();
chdir('/var/www/html/phpBB3');
include('common.php');
$user->session_begin();
chdir($zf_dir);
}
Neither in this case the scope of the global variables didn't span over the required files, so all the globals where NULL in those files.
How could I solve this issue?
I consider 2 main problems:
1. Loading resources
I dont know if you changed the code of phpBB3, since if you dont, your problem is other.
Phpbb3, as many systems, doesnt let you access directly to any file, you have to go through index.php. As you can see in common.php
if (!defined('IN_PHPBB'))
{
exit;
}
IN_PHPBB is defined in index.php, so you can simply use
Also, common.php and other files, makes use of $phpbb_root_path, that is defined in index.php.
So, at least, when you are going to include common.php you need
$zf_dir = getcwd();
chdir('/var/www/html/phpBB3');
define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './';
include('common.php');
...
chdir($zf_dir);
probably there are some other things you have to take care about.
2. Variable scopes
Also, consider than in PHP, like in almost every language, a variable declared inside a function, is considered local, and will be undefined outside that function. So for sure, if you do that inside callForumAPI(), you wont have any variable outside, and moreover, depending on where you are doing that includes...it could be actually inside a function, no matter you can notice it or not, since ZF2 is a framenwork with a complex, non-obvius architecture.
So, what i recomend, as soon as you load the file, is to use the ZF2 service manager to store all the variables and object than you would use in your application. This is a good measure even if you didnt need it,since this way you can have everything integrated as much as possible, it is important to minimize and localize access to phpbb3, since it is not meant to be a library, maintenance could be tricky, so if everyhing is in the same file, and then you create your own internal api through the service manager, it will more encapsulated and nicer. I assume you already know how to do this, if you dont, just let me know.
try this, and tell me if its enough or we need more research

Creating macros using DWScript

I read this paragraph from the Delphi Tools Site
Changes since the last SVN update are:
Added support for FreePascal-like compile-time $INCLUDE “macros”:
%FILE% and %LINE% insert the current filename and line number into the source
%FUNCTION% inserts the current function name, or class.method name into the source
%DATE% and %TIME% allow inserting the compile date/time
Is there a way we can define macros in DWScript (other than these functions) just like people define macors in excel (using VBscript) in a simple way, where the name of the script will be the name of the function that will be used later, without adding {$Include XXX} in the executed script?
N.B.: I konw this can be done by managing the written script to be saved in a certain file called functions for ex. then save the added function with its name to be used (Add), then the user will write Add(1,2) to get the result; but my boss at work wants it to be something that looks like vbscript in excel.
I'm not sure to understand the question, so I'll list various answers to various possible interpretations...
If you want to declare functions that are implicitly supported by the scripting engine without having to "{$include}" or "uses" them, you can declare them via a TdwsUnit component, and attach it to the script component. If you don't have the "coExplicitUses" option set, they'll be available automatically, and you get design-time support in the IDE.
If you want to add internal functions (that are always there), use one of the RegisterInternalFunction overloads, you can check any of the "dwsXxxxFunctions.pas" units for examples. That's potentially more efficient, but also more cumbersome.
If you want to pre-process custom source-level macros in the source code (ala C's macros), you can use the filters functionality (check the HTML or JS filters as example of how a filter can be implemented).
If you want to react dynamically to "unknown" names, so you can declare them on the spot or bind them to something dynamically, you can use TdwsLanguageExtension.FindUnknownName, that's how the RTTI environment works f.i. (see TRTTIEnvironment in dwsRTTIConnector).
If you want to parse completely custom areas of code in a completely custom way, you can use language extensions too, override ReadInstr and check how asmLib & the JSLibModule do it to support "asm".

Erlang: using include from the console?

The include directive is usually used for a .hrl file at the top of an .erl file.
But, I would like to use include from the Erlang console directly.
I am trying to use some functions in a module. I have compiled the erl file from the console. But, the functions I want to use do not work without access to the hrl file.
Any suggestions?
"But, the functions I want to use do not work without access to the hrl file."
This can't be true, but from this I'll take a shot at guessing that you want access to records in the hrl file that you don't (normally) have in the shell.
If you do rr(MODULE) you will load all records defined in MODULE(including those defined in an include file included by MODULE).
Then you can do everything you need to from the shell.
(Another thing you may possibly want for testing is to add the line -compile(export_all) to your erl file. Ugly, but good sometimes for testing.)
Have you tried the compile:file option? You can pass a list of modules to be included thus:
compile:file("myfile.erl", [{i, "/path/1/"}, {i, "/path/2/"}])
It's worth nothing that jsonerl.hrl doesn't contain any functions. It contains macros. As far as I know, macros are a compile-time-only construct in Erlang.
The easiest way to make them available would be to create a .erl file yourself that actually declares functions that are implemented in terms of the macro. Maybe something like this:
-module(jsonerl_helpers).
-include("jsonerl.hrl").
record_to_struct_f(RecordName, Record) ->
?record_to_struct(RecordName, Record).
... which, after you compile, you could call as:
jsonerl_helpers:record_to_struct_f(RecordName, Record)
I don't know why the author chose to implement those as macros; it seems odd, but I'm sure he had his reasons.

Resources