Both internal procedures and functions are accepting the parameters to give the output. So what is the use of using Internal procedures instead of functions.
A user-defined function is used when you want to perform some calculation and return a single value. In this respect it is the same as a built-in ABL function, like the SUBSTRING or EXP functions. Putting this calculation code in a FUNCTION block instead of inline in your code allows you to put it in one place and reference it multiple times without code duplication.
An internal procedure is also an encapsulated piece of code that does some work, but it is more general-purpose. While a function must return a single value, an internal procedure may or may not have input parameters or output parameters.
https://docs.progress.com/category/openedge-archives
Also functions (like methods) parameters and return value type are checked at compile time, which removes some potential problems at run time later.
The question acknowledges that both functions and internal procedures allow OUTPUT parameters and asks "what is the use" of internal procedures instead of functions.
To me, this implies that the poster is contemplating always using functions and deprecating internal procedures and is asking: "what would I lose if I do that?"
Two things spring to mind:
Sort of the opposite of Jean-Christophe Cardot's point: you would lose some automatic type conversions and syntactic flexibility about the parameter lists. Some people see that flexibility in a negative light. Others see it as a positive.
You need to "forward declare" your functions or use dynamic invocations. With an internal procedure you can RUN it without providing a declaration earlier in the code.
If you tend to think that strict type checking is useful then these are probably not benefits that you think of as being lost. If you prefer more flexible behaviors, then you may regret choosing functions rather than internal procedures.
I have seen and heard many times that Julia allows "multiple dispatch", but I am not really sure what that means or looks like. Can anyone provide me an example of what it looks like programmatically and what it enables?
From the Julia docs
The choice of which method to execute when a function is applied is called dispatch. Julia allows the dispatch process to choose which of a function's methods to call based on the number of arguments given, and on the types of all of the function's arguments. This is different than traditional object-oriented languages, where dispatch occurs based only on the first argument, which often has a special argument syntax, and is sometimes implied rather than explicitly written as an argument. 1 Using all of a function's arguments to choose which method should be invoked, rather than just the first, is known as multiple dispatch. Multiple dispatch is particularly useful for mathematical code, where it makes little sense to artificially deem the operations to "belong" to one argument more than any of the others: does the addition operation in x + y belong to x any more than it does to y? The implementation of a mathematical operator generally depends on the types of all of its arguments. Even beyond mathematical operations, however, multiple dispatch ends up being a powerful and convenient paradigm for structuring and organizing programs.
So in short: other languages rely on the first parameter of a method in order to determine which method should be called whereas in Julia, multiple parameters are taken into account. This enables multiple definitions of similar functions that have the same initial parameter.
A simple example of multiple dispatch in Julia can be found here.
The Racket FFI's documentation has types for _ptr, _cpointer, and _pointer.1
However, the documentation (as of writing this question) does not seem to compare the three different types. Obviously the first two are functions that produce ctype?s, where as the last one is a ctype? itself. But when would I use one type over the other?
1It also has as other types such as _box, _list, _gcpointer, and _cpointer/null. These are all variants of those three functions.
_ptr is a macro that is used to create types that are suitable for function types in which you need to pass data via a pointer passed as an argument (a very common idiom in C).
_pointer is a generic pointer ctype that can be used pretty much wherever a pointer is expected or returned. On the Racket side, it becomes an opaque value that you can't manipulate very easily (you can use ptr-ref if you need it). Note the docs have some caveats about interactions with GC when using this.
_cpointer constructs safer variants of _pointer that use tags to ensure that you don't mix up pointers of different types. It's generally more convenient to use define-cpointer-type instead of manually constructing these. In other words, these help you build abstractions represented by Racket's C pointers. You can do it manually with cpointer-push-tag! and _pointer but that's less convenient.
There's also a blog post I wrote that goes into more detail about some of these pointer issues: http://prl.ccs.neu.edu/blog/2016/06/27/tutorial-using-racket-s-ffi/
Have I understood correctly that in (most? some?) multiple dispatch languages each method gets added to the function at some point in time of program's execution.
Can I then conclude that multiple dispatch as a feature forces functions to be mutable?
Is there a multiple dispatch language, where all methods are attached to a (generic)function together (at load time?), so that it's not possible to see the function in different states at different points in time?
at some point in time of program's execution.
In Common Lisp the methods get added/replaced when the method definitions are executed - for a compiled system this is typically at load-time of the compiled code - not necessarily during the program's execution.
Remember, that Common Lisp has an object system (CLOS, the Common Lisp Object System), which is defined by its behaviour. It's slightly different from a language or a language extension.
Common Lisp allows runtime modification of the object system. For example also adding/removing/replacing methods.
Common Lisp also may combine more than one applicable method into an effective method, which then gets executed. Typical example: all applicable :before methods and the most specific applicable primary method will be combined into one effective method.
There exist extensions for CLOS in some implementations, which seal a generic function against changes.
For a longer treatment of the idea of an object system see: The Structure of a Programming Language Revolution by Richard P. Gabriel.
In Common Lisp, you can read the following from the specification:
7.6.1 Introduction to Generic Functions
When a defgeneric form is evaluated, one of three actions is taken (due to ensure-generic-function):
If a generic function of the given name already exists, the existing generic function object is modified. Methods specified by the current defgeneric form are added, and any methods in the existing generic function that were defined by a previous defgeneric form are removed. Methods added by the current defgeneric form might replace methods defined by defmethod, defclass, define-condition, or defstruct. No other methods in the generic function are affected or replaced.
If the given name names an ordinary function, a macro, or a special operator, an error is signaled.
Otherwise a generic function is created with the methods specified by the method definitions in the defgeneric form.
7.6.2 Introduction to Methods
When a method-defining form is evaluated, a method object is created and one of four actions is taken:
If a generic function of the given name already exists and if a method object already exists that agrees with the new one on parameter specializers and qualifiers, the new method object replaces the old one. For a definition of one method agreeing with another on parameter specializers and qualifiers, see Section 7.6.3 (Agreement on Parameter Specializers and Qualifiers).
If a generic function of the given name already exists and if there is no method object that agrees with the new one on parameter specializers and qualifiers, the existing generic function object is modified to contain the new method object.
If the given name names an ordinary function, a macro, or a special operator, an error is signaled.
Otherwise a generic function is created with the method specified by the method-defining form.
The definition of ensure-generic-function:
If function-name specifies a generic function that has a different value for the :lambda-list argument, and the new value is congruent with the lambda lists of all existing methods or there are no methods, the value is changed; otherwise an error is signaled.
If function-name specifies a generic function that has a different value for the :generic-function-class argument and if the new generic function class is compatible with the old, change-class is called to change the class of the generic function; otherwise an error is signaled.
If function-name specifies a generic function that has a different value for the :method-class argument, the value is changed, but any existing methods are not changed.
You also have add-method and remove-method.
As you can see, generic functions retain their identify between defmethod definitions, and even between defgeneric definitions. Generic functions are mutable in Common Lisp.
In Julia, you can read the following from the documentation:
Defining Methods
To define a function with multiple methods, one simply defines the function multiple times, with different numbers and types of arguments. The first method definition for a function creates the function object, and subsequent method definitions add new methods to the existing function object.
As you can see, functions objects are mutable in Julia.
This says nothing about all other multiple dispatch languages. You can invent a multiple dispatch language right now just for the purpose of showing you can do it with immutability, e.g. adding methods would return a new function similar to the previous function but with the added method. Or a language where functions are generated statically at compile-time, such that you can't change it at runtime in any way, not even to add or remove methods.
Paraphrasing from the excellent "Getting started with Julia" book which has a nice section on this (emphasis mine):
We already saw that functions are inherently defined as generic, that is, they can be used for different types of their arguments. The compiler will generate a separate version of the function each time it is called with arguments of a new type. A concrete version of a function for a specific combination of argument types is called a method in Julia. To define a new method for a function (also called overloading), just use the same function name but a different signature, that is, with different argument types.
A list of all the methods is stored in a virtual method table ( vtable ) on the function itself; methods do not belong to a particular type. When a function is called, Julia will do a lookup in that vtable at runtime to find which concrete method it should call based on the types of all its arguments; this is Julia's mechanism of multiple dispatch, which neither Python, nor C++ or Fortran implements. It allows open extensions where normal object-oriented code would have forced you to change a class or subclass an existing class and thus change your library. Note that only the positional arguments are taken into account for multiple dispatch, and not the keyword arguments.
For each of these different methods, specialized low-level code is generated, targeted to the processor's instruction set. In contrast to object-oriented (OO) languages, vtable is stored in the function, and not in the type (or class). In OO languages, a method is called on a single object, object.method(), which is generally called single dispatch. In Julia, one can say that a function belongs to multiple types, or that a function is specialized or overloaded for different types. Julia's ability to compile code that reads like a high-level dynamic language into machine code that performs like C almost entirely is derived from its ability to do multiple dispatch.
So, the way I understand this (I may be wrong) is that:
The generic function needs to be defined in the session before you can use it
Explicitly defined methods for concrete arguments are added to the function's multiple-dispatch lookup table at the point where they're defined.
Whenever a function is called with specific arguments for which an explicitly defined method does not exist, a concrete version for those arguments is compiled and added to the vtable. (however, this does not show up as an explicit method if you run methods() on that function name)
The first call of such a function will result in some compilation overhead; however, subsequent calls will use the existing compiled version*.
I wouldn't say this makes functions mutable though, that's an altogether different issue. You can confirm yourself they're immutable using the isimmutable() function on a function 'handle'.
*I know modules can be precompiled, but I am not entirely sure if these on-the-fly compiled versions are saved between sessions in any form -- comments welcome :)
Dynamicity can be a real asset in your application, if only for debugging. Trying to prevent a function from being later updated, redefined, etc. might be a little bit short-sighted. But if you are sure you want static dispatch, you can define your own class of generic functions thanks to the MOP, the Meta-Object Protocol, which is not part of the standard but still largely supported. That's what the Inlined-Generic-Function library provides (and this is possible because CLOS is open to extensions).
In Dylan, methods are generally added to a generic function at compile time, but they may also be added at run time (via add-method or remove-method). However, a generic function may be sealed, which prevents libraries other than the one in which the g.f. is defined from adding methods. So to answer your question, in Dylan generic functions are always mutable within the defining library but they may be rendered immutable to other libraries.
This question already has answers here:
Pointers vs. values in parameters and return values
(5 answers)
Closed 7 years ago.
I'm new to the Go Language, and have only minimal background in C/C++, so naturally I'm struggling with the idea of when to use pointers and when not to use pointers. Although this question might be considered open-ended, I'm wondering what some guidelines on when to return structs and when to return pointers, (and equivalently when to accept structs / pointers as arguments).
From what I can guess, the following statements hold true:
structs are passed into functions by value. That is, a copy of a structure is made when passing it into a function.
if I want to pass a structure by reference, then I would instead use a pointer argument in the function definition, and use the addressof operator when calling the function.
The reason why I would want to pass in a structure by reference is because either the structure I'm passing in is large, and it would be taxing on memory to pass it by value (unlikely) or if I want to make changes to the copy that I'm passing in (more likely).
As a corollary to 3.), I should pass by value unless I have one of the reasons above to pass by reference.
Are my assumptions correct? Or am I missing the mark on pointers?
Your assumptions are correct. About #3, Go is concurrent language and passing by reference in goroutines make them all read same structure which is safe, but also make them modify same structure which is dangerous.