How would you do a functionally pure linked list in C? Is a linked list what I should even be doing? I'm trying to have a list of objects but I can't think of how to add an item to the list from a function without modifying outside states.
I basically want this:
void AddItemToList(Item item);
To be able to be called from anywhere, without the caller having to worry about what list is being added to.
Right now I just have:
void AddTypeToList(entityType_t *type, entityType_t *listHead)
{
type->next = listHead;
listHead = type;
}
void RegisterEntityType(entityType_t *type)
{
AddTypeToList(type, typeList);
}
But this is obviously not functional (or is it?) because RegisterEntityType is modifying typeList. (which is a global entityType_t)
You'd need a different function, generically speaking,
List AddItemToList(List list, Item item);
Because you should return a new list with the item added, without modifying the original list. This involves other questions, such as that a Garbage Collector should be needed in order to keep track of the intermediate lists your are going to create and discard.
I don't think that C is the best language to implement functional programming techniques, you'll have to build everything from the ground up. The obvious, ideal choice would be a pure functional programming language, or at least a programming language with support for functional techniques, such as for example C++, C# or Python.
Maybe you would like to check this question.
Hope this (somehow) helps.
Related
I'm having an Algorithms course next semester and so I dived into C with the purpose of making a few data structures ahead of time to be prepared.
As I learned about function pointers, I found I could store them in structs and create an object-oriented-like use for my data structure. Here's an example:
#include <stdio.h>
void insert(char * object)
{
printf("Adding %s to the data structure\n", object);
}
typedef struct data_structure {
char * obj;
void (*insert)(char * object);
} data_structure;
int main()
{
data_structure d;
d.insert = insert;
d.insert("bacon");
return 0;
}
But is this kind of procedure actually useful in the scope of data structure and algorithm studying in C? Or is it just taking up memory on the data structure?
I've found other posts talking about function pointers, but none that explores this kind of approach. I think this could be useful to a bunch of curious students out there :)
In the past I have certainly seen objects constructed this way as sets of function pointers effectively representing a vtable. Usually, for a vtable you add one extra level of indirection such that all data objects with similar traits point to the same function pointer object. This reduces the cost per data object if there is more than 1 function, but at a slight execution cost.
It can also be used as a lightweight way to organise and structure function+voiddata callback objects, by insisting that the first member of the data is the callback function. Of course, you can't define inherited classes using c, but you can have nested structures which can be bullied to the same purpose.
After reading all the answers, here's the insight this post gathered regarding the use of function pointers as C structure attributes.
Advantages:
Good ol' practise on a somewhat advanced subject if you're a student
Provides encapsulation and object oriented code in C
Gives you better understanding of the object orientated programming paradigm if you're not already well familiarized with it
Can be used to implement VTables
Disadvantages:
On a functional level, you still have to pass the data structure to the function, as it doesn't have access to said data structure
Slight performance overhead
In conclusion, the use of function pointers as in the original question would really only have practical uses if one wishes to explore OOP whilst getting into more advanced aspects of C, or to construct VTables.
Thank you to all the people who replied.
I decided to polish my knowledge of data structures and came across linked list.
I was wondering if anyone has any practical example of where do we use them in relation to mobile development or any other kind of projects that use swift as their language since to me it seems the Array class already has enough flexibility as it is.
You should use linked lists anytime you need their primary benefit: O(1) insertion and deletion at arbitrary points in the list.
The mistake most people make with linked lists is trying to implement them as a value type in Swift. That's very hard, and the resulting data structure is generally useless. The most common form is with an enum:
enum List<T> {
indirect case Cons(T, List<T>)
case Nil
}
let list = List.Cons(1, .Cons(2, .Cons(3, .Nil)))
I've never seen anyone come up with an efficient implementation of that. Efficient collections in Swift require copy-on-write, and that's very hard to build for an enum.
The natural way to build linked lists in Swift is as a mutable reference type. That's very easy to make efficient and is very useful.
class List<T> {
var value: T
var next: List<T>?
init(_ value: T, _ next: List<T>?) {
self.value = value
self.next = next
}
}
let list = List(1, List(2, List(3, nil)))
And in that form, you'd use it any time you want O(1) insertion and deletion at arbitrary points in the list.
You could also build this as an immutable reference type (using let) if you had several large lists that shared a significant tail. I've never seen that come up in practice.
Most folks I know who go down this route want an immutable linked list so they can implement the many very beautiful recursive algorithms that are built on them and which are very common in FP languages (this may say more about the people I know than the question itself). But Swift is at best mildly hostile to recursion, so this is rarely worth the trouble IMO except as an exercise. But recursive algorithms are just one use of linked lists. As an O(1) arbitrary-insertion data structure they're as useful in Swift as they are in Pascal and C, and you build them roughly the same way.
In implementing a single linked list in C, I think there are three ways :
HEADER IS A POINTER ITSELF.IT POINTS TO THE FIRST NODE OF THE LINKED LIST.
1.Declare the header globally and use function void insert(int) to insert.This should work as header is global.
2.Declare header inside main and use function node*insert(node*) to insert.This should work because of the return involved.
3.Declare header inside main and use function void insert(node**) to insert.
Sometimes the second way works even without the return involved. Why?
Which is the better way?
If the functions involved are recursive as in tree which method is appropriate?
You should encapsulate your data structure in a single object (the head node or a struct that contains it), and then you can have your functions work on that object. This means that you can have more than one linked list in your program (that won't work with a global head node) and you can also pass it around to different functions that want to use it (there's no point having a data structure without being able to use it).
If you have your single object (head node) stored in your program then the insert and delete functions don't need to return anything, as you already have a pointer to the object that represents the linked list.
If the functions involved are recursive as in tree which method is appropriate?
The functions should not be recursive "as in tree". The depth of a tree is O(logn), which means recursion is reasonable in many situations; The size of a linked list is O(n), which means recursion can easily overflow the stack.
I am new to C. I have no idea about how to write a C function which creates an empty queue and return a void pointer.
void* queue_open(void)
I also want to know how to write a C function which puts an element at end of a queue.
void queue_put(void *p, void *elementp)
Thanks for your help!
If you are coming from an object oriented background (as your method signatures seem to indicate).
Object oriented idea -> good way to do it in C
Object creation -> malloc a struct, then pass it into an initialization function
struct queue* q = (struct queue*)malloc(sizeof(struct queue));
queue_initialize(q);
if you want, you can wrap this in a function, like so
struct queue* queue_construct() {
struct queue* q = (struct queue*)malloc(sizeof(struct queue));
queue_initialize(q);
return q;
}
Note that these pointer shouldn't point to void*, let C do at least some of the type checking for you.
Implement a method -> create a function that takes a struct pointer to the "almost this" struct.
struct user* user = ... whatever we do here ...;
queue_add(q, (void*)user);
As far as how to actually implement a queue, I suggest a good data structures or algorithms book, as there are many ways to go about it; and, the specific techniques you choose will have different impacts on performance and reliability. There's no one best way, it depends heavily on how the queue is to be used, and which aspects of performance are more important.
The book I recommend is Introduction to Algorithms. This book is overkill for most situations, with very detailed listings of nearly every major data structure you are likely to encounter in the first few years of programming. As such, it makes a great reference, despite its attempt at a language neutral approach, which now looks odd when compared to common programming languages.
Once you understand what is going on, you can do it in nearly any language.
You need to decide what a queue element should look like, what a queue is, and what it means for a queue to be empty. If you know those things, writing queue_open and queue_put should be pretty easy. I'd suggest that you start by defining a structure that represents your queue element.
You can learn about queues here:
http://en.wikipedia.org/wiki/Queue_(data_structure)
While you could easily copy and paste the sample code from the link above and with little modification solve your homework problem, you are not going to learn a lot by doing that.
After understanding a queue conceptually, I recommend you try to implement it yourself, then use the sample code from the link above as a reference when you get stuck.
The best thing you could do is pair up with another student in your class who is smarter than you. Then pair program ( http://en.wikipedia.org/wiki/Pair_programming ) with him/her to solve the problem. You'll become a better programmer.
Quoting a code snippet :
/**
* list_add - add a new entry
* #new: new entry to be added
* #head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
I have seen similar code in several different programs, especially those manipulating data structures. What is the usual intention in adding this extra level of indirection - why can't the code inside __list_add be put inside list_add ?
If you copy code, it will make maintenance harder. In this example, the extra level of indirection hides the parameter next. It will provide a function with just 2 parameters rather than 3.
If the code inside the __list_add() is copied, it needs to be copied to multiple places. If then the list mechanism is changed somewhat, all of these places need to be updated too, or bugs will start to pop-up (i.e. a FIFO and LIFO implementation of a list show different behavior).
There is always a tradeoff; another level of indirection also adds complexity and possibly overhead, as opposed to duplicating lines of code or having lots of parameters in the API.
It's about code reuse, and avoiding duplication.
__list_add() contains code that is useful in more situations than just this one, and can be shared between several different functions.
Sharing code like this has several advantages:
If there's a bug in __list_add() and you fix it, all the functions that use it get the fix.
If __list_add() gets an enhancement (eg. you make it faster) all the functions get faster.
There's only one place to look when you want to see how items are added to lists.
It can.
However, there are probably other public entries that can share the code in __list_add(). eg, there may be a push() or an insert_head() or something like that.
NOTE: If this is C++ then you might want to rethink calling your variables new, as this is a reserved word.
__list_add will be intended as a "private" internal function which might have multiple uses internally. The public facing list_add is there as a convenient wrapper around it.
This wrapper is inline. If you added the body of __List_add, that too would be inlined. The apaprent goal is to just inline the pushing of the extra head->next argument and nothing else.
That function comes from the linux kernel.
It belongs to the generic list implementation:
Take a look: __list_add()
__list_add() is used in many places: e.g. list_add() which adds an element at a list head, list_add_tail() which adds an element at list tail... It can also be used to insert an element at a given position.
It is also common to define an wrapper function for recursive functions so the initial parameters are set correctly.
See binary search on wikipedia for Recursion (computer science)
Could also be to keep binary compatibility. you have an indirection that allows to keep the ABI invariant.
From http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
When a new version of a library is
binary-incompatible with the old one
the soname needs to change. In C,
there are four basic reasons that a
library would cease to be binary
compatible:
The behavior of a function changes so that it no longer meets its
original specification,
Exported data items change (exception: adding optional items to
the ends of structures is okay, as
long as those structures are only
allocated within the library).
An exported function is removed.
The interface of an exported function changes.