[–]▶ No.1024920>>1024929 >>1024966 >>1024972 >>1024983 >>1025087 >>1025146 >>1025741 >>1025745 [Watch Thread][Show All Posts]
> Just wrote my first linkedlist struct in C
> Totally recursive
It's a good day.
Check it out/give me feedback: https://termbin.com/7dan
▶ No.1024924
>>1024921
I thought I'd post on there, but it's slow as hell, and there are tons of posts that ought to belong on /prog/ here.
▶ No.1024927>>1024932 >>1025087
>recursive
enjoy blowing your stack and crashing the program when you have more than a few elements
▶ No.1024929>>1024943 >>1025087
>>1024920 (OP)
>recursive
Retarded.
▶ No.1024932>>1024941 >>1025087
▶ No.1024941>>1024965 >>1025087
>>1024932
Does his nodeLen function look amenable to tco?
▶ No.1024943>>1024944 >>1024956
>>1024929
It's obviously an exercise in programming. It's retarded, but so is Hello World.
▶ No.1024944
>>1024943
Well as long as the student realizes the shortfalls, then lesson learned.
Hello World will soon become the new FizzBuzz as more retards "learn2code".
▶ No.1024956>>1024966
>>1024943
These days you cannot even send someone a Hello World program to their device (iPhone) without paying Apple $100 for the privilege of signing the application, and that's if they still allow apps outside their appstore.
It's over. Programmers used to be able to share programs with people, now we live in a sanitized world where everything has to be approved by corporate. We lost. We fought amongst ourselves in silly KDE vs GNOME type battles, meanwhile the enemy plotted our demise with the iPhone revolution. We ceded ground to the hordes, and now they police our internet. There's no hope.
▶ No.1024960>>1024962 >>1024963 >>1025087
Explicit recursion is just as bad as GOTO
▶ No.1024962
>>1024960
There is literally nothing wrong with goto
▶ No.1024963>>1024976
>>1024960
As apposed to what, explicit looping? recursion schemes?
▶ No.1024966>>1024979
>>1024956
Use Android, fag.
>>1024920 (OP)
Never use recursion, unless you know how to not blow a stack.
▶ No.1024969>>1024979
>>1024965
>any optimization involving recursion is TCO
look faggot take a look at the 101
https://en.wikipedia.org/wiki/Tail_call
The code posted is literally not in tail position and cannot be TCOd. The compiler is doing something totally different here.
▶ No.1024972>>1025744
>>1024920 (OP)
#include <stdlib.h>
#include <limits.h>
What did he mean by this?
▶ No.1024976>>1024978
>>1024963
Yes, recursion schemes offer constructs for handling and reasoning about recursion just like while and for provide abstractions over using GOTO to loop.
▶ No.1024978
>>1024976
Ah yes like the good old Zygohistomorphic prepromorphism pattern
▶ No.1024979>>1024986 >>1024991
>>1024966
>use googles os
No thanks
>>1024969
If it turns recursion into iteration, who cares how it happens?
▶ No.1024982>>1025087
Good, we need more C anti-rust shills here
▶ No.1024983>>1025025 >>1025087 >>1025243
>>1024920 (OP)
scalar_list.ads:
generic
type Item is private;
with function "+" (Left, Right : in Item) return Item;
package Scalar_List is
type Cell;
type Node is access all Cell;
type Cell is tagged record
X : Item;
Next : Node;
end record;
List_Out_Of_Bounds : exception;
procedure Append (This : in Node; X : in Item);
function Nth (This : in Node; Depth : in Natural) return Node;
procedure Get (This : in Node; Depth : in Natural; X : out Item);
procedure Set (This : in Node; Depth : in Natural; X : in Item);
procedure Increment (This : in Node; Depth : in Natural; X : in Item);
function Length (This : in Node) return Natural;
end Scalar_List;
scalar_list.adb:
package body Scalar_List is
procedure Append (This : in Node; X : in Item) is
N : Node := new Cell'(X => X, Next => null);
P : Node := This;
begin
while P.Next /= null loop
P := P.Next;
end loop;
P.Next := N;
end Append;
function Nth (This : in Node; Depth : in Natural) return Node is
D : Natural := Depth;
P : Node := This;
begin
while D > 0 loop
D := D - 1;
P := P.Next;
if P = null then
raise List_Out_Of_Bounds;
end if;
end loop;
return P;
end Nth;
procedure Get (This : in Node; Depth : in Natural; X : out Item) is
begin
X := Nth (This, Depth).X;
end Get;
procedure Set (This : in Node; Depth : in Natural; X : in Item) is
begin
Nth (This, Depth).X := X;
end Set;
procedure Increment (This : in Node; Depth : in Natural; X : in Item) is
N : Node := Nth (This, Depth);
begin
N.X := N.X + X;
end Increment;
function Length (This : in Node) return Natural is
Depth : Natural := 0;
P : Node := This;
begin
while P /= null loop
Depth := Depth + 1;
P := P.Next;
end loop;
return Depth;
end Length;
end Scalar_List;
listex.adb:
with Ada.Text_IO; use Ada.Text_IO;
with Scalar_List;
procedure Listex is
subtype Faggotry is Float range 0.0 .. 10.0;
package Poster_List is new Scalar_List (Item => Faggotry, "+" => "+");
Posters : Poster_List.Node :=
new Poster_List.Cell'(X => 10.0, Next => null);
F : Faggotry;
begin
Poster_List.Append (Posters, 3.0);
Poster_List.Append (Posters, 2.0);
Poster_List.Append (Posters, 0.0);
Poster_List.Append (Posters, 4.0);
Poster_List.Get (Posters, 0, F);
Put_Line ("OP : " & Faggotry'Image (F));
Poster_List.Get (Posters, 3, F);
Put_Line ("Ada: " & Faggotry'Image (F));
end Listex;
output:
$ ./listex
OP : 1.00000E+01
Ada: 0.00000E+00
want methods? want higher order functions? want to use one that closes over a stack-allocated variable (without dynamic memory allocation)? Want this to not leak and use explicit deallocation? Want this to not leak because it gets deallocated when the head of the list goes out of scope? Want to have a numeric type list instead of a list of "something with a + function, lol"?
You can do that with Ada, too.
▶ No.1024986
>>1024979
>who cares how it happens?
Not GenZ, that's for sure.
▶ No.1024991>>1025118 >>1025121
>>1024979
>If it turns recursion into iteration, who cares how it happens?
Not all recursion can be turned into plain looping
▶ No.1025025>>1025113
>>1024983
What are good resources for getting into ada?
▶ No.1025087>>1025109 >>1025113
>>1024920 (OP)
OP again
>>1024929
>>1024927
Pls no bulli
>>1024960
Is there a way to do this in C? I think that would require an anonymous function?
>>1024982
godspeed
>>1024983
Language shill, to be expected
>>1024927
>>1024932
>>1024941
I wrote a new version that "should" be tail-call optimized: https://termbin.com/ncy3
▶ No.1025109
>>1025087
>I wrote a new version that "should" be tail-call optimized:
How about you make it iterative instead of relying on an optimization that neither GCC nor LLVM guarantee?
▶ No.1025113>>1025117
>>1025087
a way to do what in C? explicit recursion? That's called a function call. You're doing it already. GOTO? that's a feature of the language. The syntax is 'goto some_label;', after you've prefaced some other statement with label:
>Language shill, to be expected
so you prepared yourself to ignore any comments about other languages? Languages aren't cults ... with some exceptions. Relax and prepare to defend your decisions instead of blindly adhere to them.
"I don't know jack about jack but I won't know anything if I don't finish learning something" is a good enough reason to stick with C for now.
Later, learn Ada. You'll appreciate it more.
>>1025025
I started with "Introduction to Ada Programming" and "Programming in Ada 2012", both books.
http://ada-auth.org/ has standards docs. I've pulled up https://en.wikibooks.org/wiki/Ada_Programming and Rosetta Code a few times. GNAT's libraries are documented by their .ads files pretty much. You can find them on your own system and at https://www2.adacore.com/gap-static/GNAT_Book/html/rts/
▶ No.1025117>>1025122
>>1025113
Calm down, Ada shill.
▶ No.1025118>>1025121 >>1025122
▶ No.1025121
▶ No.1025122>>1025124
>>1025117
I AM FUCKING CALM YOU PIECE OF SHIT
>>1025118
yes, obviously. Write something recursive that walks a tree. Like a filesystem. An example of "non-plain" iteration would be iteration with a stack that you manage yourself.
▶ No.1025124>>1025125
▶ No.1025125>>1025126
>>1025124
>>An example of "non-plain" iteration would be iteration with a stack that you manage yourself.
>what could he mean by this?
▶ No.1025126>>1025128
>>1025125
>>what could he mean by this?
I actually don't know. What is ""non-plain" iteration"?
▶ No.1025128>>1025129
>>1025126
>>>An example of "non-plain" iteration would be iteration with a stack that you manage yourself.
>What is ""non-plain" iteration"?
Jesus Christ.
Q: I have some tail-recursive code. How do I make this iterative?
A: put an infinite loop around it, replace your returns with loop exits, and replace your tail-recursive calls with variable assignment.
Q: oh wow, that's actually really easy. Tail-recursive code is basically already iterative code, huh.
A: In SICP terms you have an iterative process either way.
Q: I have some recursive code that isn't tail-recursive. Is this already iterative code like in the last example?
A: nope.
Q: phwaaaaaaah?
A: non-tail-recursive recursive code is using the stack as a data structure. So when you take out the recursion, you need a replacement store for all that data.
▶ No.1025129>>1025132 >>1025133
>>1025128
>hurr durr u stoopid
>let me explain you cs 101
Thanks dude. I already know this.
You can turn any recursive algorithm into an iterative algorithm. It doesn't matter how much you try to redefine what looping means.
▶ No.1025132
>>1025129
Get used to over exaggerated smugness in CS, it’s not going away.
▶ No.1025133>>1025135
>>1025129
>>>>you can turn y blahs into foos, but non-y blahs you can only turn into x foo.
>>>YEAH BUT WHAT DOES X MEAN
>>it means the obvious fucking thing, you moron
>YEAH BUT YOU CAN TURN BLAHS INTO FOOS
>I ALREADY KNOW THIS
k. When you stop LARPing and actually write some code, you'll care about the difference.
▶ No.1025135>>1025136
>>1025133
Mikee, is this you?
▶ No.1025136
>>1025135
yes it's me. every other poster in /tech/ that isn't you is actually me.
▶ No.1025146>>1025153
>>1024920 (OP)
Looks fine to me, but some points:
> recursion
Tail-call optimization is not guaranteed by the standard, so your compiler might do it, but it also might not. If a problem can be solved iteratively that's generally the way to go. There is nothing wrong with recursion if the problem itself is recursive. And if you are doing this just as an exercise in recursion that's OK as well. Just be mindful of the possible issue.
> use designated initializers
Initializing a struct the old way (as explained in K&R) is dangerous because the order of fields could change. Designated intializers allow you to explicitly name each field:
struct Node d = {.x = 4.0, .next = NULL};
> Non-mutating prepend
You should have a 'prepend' function to complement 'append':
struct Node prepend(struct Node* list, double value) {
return (struct Node) {.x = value, .next = list};
};
This function does not alter the remainder of the list, so it can be used to safely add new items to the list without affecting any code that's using older items. This is a big advantage of linked lists over other data structures. You should also have a 'head' and 'tail' like they usually do in functional programming languages.
double head(struct Node* list) {
return list->x;
}
double tail(struct Node* list) {
return list->next;
}
The 'head' is not very interesting, but 'tail' allows you to "drop" values from the list without mutating it.
▶ No.1025153>>1025159
>>1025146
>iteratively
REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
YOU CAN'T DO THAT BECAUSE IS ISN'T PLAIN LOOPING.
YOU CAN'T JUST TURN BLAHS INTO FOOS
▶ No.1025159>>1025163 >>1025184
>>1025153
yeah it's real weird how non-LARPers keep wanting to distinguish between
A) completely trivial refactoring, and
B) the addition of a data structure that you must now manage and make some decisions about, and which might not just have data in it but, also functions
why would people distinguish between no work and some work? it's a real mystery. Must be some smug CS bullshit.
▶ No.1025163>>1025164 >>1025184
>>1025159
>It isn't "real" looping when you explicitly manage your own stack
Yeah. I'm the LARPer.
▶ No.1025164>>1025166
>>1025163
>>"non-plain"
>do you mean "non-real"?
yeah you are.
▶ No.1025166>>1025175
>>1025164
>muh plain/non-plain looping
no u
▶ No.1025175>>1025183
>>1025166
>blow the stack in an application
>np, let's make this iterative
>notice that the code isn't tail recursive
>feel nothing at all
>no anon, that wasn't a sigh. all iterative code is the same to me. I'm not unhappy about this at all.
>I'm not one of them looper racists. I can't even tell the difference between kinds of loops.
▶ No.1025183>>1025242
▶ No.1025184>>1025187
>>1025159
>>1025163
>LARP
typing on the computer is not live action role playing, you double niggers
▶ No.1025187>>1025189
>>1025184
How are you typing non-live?
How is arguing with stupid niggers on here not action?
How is pretending to be a programmer not role playing?
▶ No.1025189>>1025190 >>1025191
>>1025187
>How is pretending to be a programmer not role playing?
it is, but it's not live action, though
▶ No.1025190
>>1025189
How are you typing non-live?
How is arguing with stupid niggers on here not action?
▶ No.1025191
>>1025189
>this greentext was prerecorded before a live studio audience
▶ No.1025222>>1025224
@Anonymous
>stupid nigger
wow just wow. First you can't even understand how to iterate in a functionally elegant style and then you start with the racism. You are so pathetic.
▶ No.1025224
>>1025222
>@Anonymous
>don't offent my equality cult
If this is bait, stop shitposting, if this isn't, go back to your shithole. Nigger.
▶ No.1025242
▶ No.1025243>>1025246
>>1024983
Here's a nicer append; I haven't written much Ada yet, but this is O(1) time complexity:
procedure Append (This : in out Node; X : in Item) is
N : Node := new Cell'(X => X, Next => This);
begin
This := N;
end Append;
I haven't checked this compiles, but it looks like it should.
▶ No.1025246>>1025248
>>1025243
Looks like you're writing a prepend.
▶ No.1025248>>1025272
>>1025246
Oh. I usually use Common Lisp and there's not much of a distinction there, because CL:APPEND is variadic. If you just care about getting things into the list and don't need the ordering of the append that was written, I'd rather use this.
▶ No.1025272>>1025273 >>1025313
>>1025248
> because CL:APPEND is variadic
You seem confused about the terminology. CL:APPEND is a typical non-destructive append, and it has to walk it's way to the end of the leftmost list O(n).
▶ No.1025273>>1025331
>>1025272
Also. If you want Append and Prepend to operate in O(1) time, you'll need to use a double ended queue (dequeue).
https://en.wikipedia.org/wiki/Double-ended_queue
▶ No.1025280
good job, anon. keep learning.
▶ No.1025312
>/tech/ falls for the bait again, why am I not surprised?
▶ No.1025313
>>1025272
Yeah. If you were just adding a single element, you'd use CL:CONS or CL:LIST*. I mentioned CL:APPEND in part because of the similar names. It's also worth mentioning the destructive append, CL:NCONC, still doesn't modify the rightmost list.
▶ No.1025331>>1025353
>>1025273
dequeue is better than list in every way prove me wrong
▶ No.1025353
>>1025331
if the extra functionality of a dqueue is of no use to you, then it's just a worse implementation of a list.
▶ No.1025741>>1025747
>>1024920 (OP)
hey friend. dont let the negative people here get you down. you've written more code than at least half the people in this thread. :)
congratulations! just keep learning and you'll go places ^_^
▶ No.1025744>>1025746
>>1024972
Try searching "include statement c" on your favorite search engine.
▶ No.1025745
>>1024920 (OP)
>double get
▶ No.1025746>>1025812 >>1026013
>>1025744
Actually anon that is not the c language but rather a processor script. You can use it in anything.
▶ No.1025747>>1025749
>>1025741
>you've written more code than at least half the people in this thread
Not likely anon
▶ No.1025749
>>1025747
Yeah, pretty unlikely.
Unless he means in the last month in which case he got me at least.
▶ No.1025812
>>1025746
There aren't actually that many C programmers. They mostly are cpp programmers since they write code that is for the C preprocessor.
▶ No.1026013>>1026120
>>1025746
Anything that has the exact same tokenization rules as c that is.
▶ No.1026047>>1026066 >>1026127
typedef struct { void *car, *cdr; } pear;
struct pear *pare(void *car, void *cdr)
{
pear *p = malloc(sizeof(pear));
return (*p = (pear){car, cdr}, p);
}
void *fold(void *(f*)(void*,void*), void *i, struct pear *p)
{
for (; p; i = f(p->car, i), p=p->cdr);
return i;
}
pear *reverse(pear *p) { return fold(&pare, NULL, p); }
wow such hard.
▶ No.1026066>>1026125
>>1026047
>pear
>pare
>comma operator to save one line of code--when you have shittybraces!
>f* when you meant *f in function pointer
>error: dereferencing pointer to incomplete type ‘struct pear’
>"wow such hard" - trying to slap a face that hasn't presented itself?
▶ No.1026120
>>1026013
Wrong. It is used in Haskell all the time.
▶ No.1026125
>>1026066
You have to be good at c to be able to write it this badly.
▶ No.1026127>>1026130
>>1026047
lol, why are you even declaring a pointer in your first function, just return from malloc because it already returns a pointer anyways.
▶ No.1026130>>1026132
>>1026127
So that he can initialize the cons cell.
▶ No.1026132
>>1026130
You're right.
My dumb ass error.