Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
hepatizon
Oct 27, 2010
monads alienate people because learning stupid syntax (haskell, lambda calculus) is painful

Adbot
ADBOT LOVES YOU

MeruFM
Jul 27, 2010
so
new_array = array1.join(array2)
is better than
join_arrays(array1, array2)
?

I thought php proved that 15 years ago

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

fart simpson posted:

monads, specifically, are really common in haskell, specifically. there's functional programming languages that don't use them so much, and they're not a magical thing that you should care much about if you aren't using haskell? i don't really understand why people talk about them so much. it seems like there's a myth built up around them which causes people to react badly

I have a problem: writing maintainable asynchronous code in C or C++ (preferably C++). with a requirement: without using threads. I get told by people purporting to be smart that futures/promises are the solution I'm looking for, but too smart they can't be, because the solution they propose sucks. I ask for generator functions or stackless coroutines (preferably both), swearing high and low that it's what I really need the smart people give me monads, and how unfortunate that I cannot elevate myself from my muddy imperative programming rut and emancipate my code from such short a leash...

FamDav
Mar 29, 2008
just wanna check who is telling you that you need monads besides barto's blog post

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

FamDav posted:

just wanna check who is telling you that you need monads besides barto's blog post

monads specifically I don't know but I see a lot of unwarranted gushing over futures/promises. which are poo poo, I've used them when they were called OVERLAPPED and when they were called struct aiocb and when they were called IAsyncResult and they always always sucked. we use them because we have no choice, dressing them up with a next() method doesn't make them smell less

sometimes I wonder why C doesn't have a "program" data type. something like (lovely example, <- not a language designer):
C++ code:
#include <ctype.h>
#include <stdio.h>

program async_uppercase {
	int main()
	{
		while(!feof(stdin))
		{
			fputc(toupper(getc(stdin)), stdout);
		}
	}
}

int main()
{
	program async_uppercase uc;
	FILE *in = string_open("string");
	FILE *out = stringbuf_create();

	prog_init(&uc);
	prog_set_stdin(&uc, in);
	prog_set_stdout(&uc, out);
	prog_start(&uc);
	prog_wait(&uc);

	fclose(in);

	assert(strcmp("STRING", stringbuf_string(out)) == 0);
	fclose(out);
}
threads are terrible in C, the quintessential C program is single-threaded, reading from input, writing to output. why did we get lovely threads instead of subprograms?

e: code in C and C++ is structured with lists of statements. this is why we got threads, this is why we got lambdas/blocks, this is why I long for await/yield. chaining callbacks: poo poo code, unreadable, unmaintainable. call them monads, still poo poo, unreadable, unmaintainable. await/yield: clear intentions, clear behavior, if and while and for and switch are their usual selves and not bizarro s-expressions-lite. these people are in all seriousness proposing a DSL as a general solution for a general C++ problem, and well we didn't use boost::lambda because we liked bizarro s-expressions

hackbunny fucked around with this message at 03:00 on Nov 10, 2014

Deacon of Delicious
Aug 20, 2007

I bet the twist ending is Dracula's dick-babies
why is computer thing bad?! every other computer thing is good and well designed

computers are terrible and we are terrible at computers

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av
why can't I write C++ in C++. why do I ask for a C++ solution and the answer is "what if you wrote Scheme in C++", "what if you wrote Haskell in C++"

brap
Aug 23, 2004

Grimey Drawer
are await/async more than just ways of dressing up callbacks in a way that makes them readable?
sorry if this is insanely ignorant

Bloody
Mar 3, 2013

is Parallel.ForEach in c# a monad

asking 4 a friend

gonadic io
Feb 16, 2011

>>=

Bloody posted:

is Parallel.ForEach in c# a monad

asking 4 a friend

is it an object that implements bind and return?

Bloody
Mar 3, 2013

i dont know

Bloody
Mar 3, 2013

but it does parallel things for me and hackbunny was just complaining about parallel things

Bloody
Mar 3, 2013

i also dont know the difference between async/await and just doin things in parallel

Bloody
Mar 3, 2013

i suspect there is no difference but im not sure

Deacon of Delicious
Aug 20, 2007

I bet the twist ending is Dracula's dick-babies

hackbunny posted:

why can't I write C++ in C++.

because nobody can write c++

Gazpacho
Jun 18, 2004

by Fluffdaddy
Slippery Tilde

hackbunny posted:

why can't I write C++ in C++. why do I ask for a C++ solution and the answer is "what if you wrote Scheme in C++", "what if you wrote Haskell in C++"
threads are the primo model for asynchronous programming in C and C++ due to their stack-based proceduralism. i think you have to accept that any other model in those languages is going to be hard

read the lauer/needham paper if you haven't already

pseudorandom name
May 6, 2007

hackbunny posted:

why can't I write C++ in C++. why do I ask for a C++ solution and the answer is "what if you wrote Scheme in C++", "what if you wrote Haskell in C++"

hint: C++ is garbage and the people in charge of the specification live in ivory towers

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

fleshweasel posted:

are await/async more than just ways of dressing up callbacks in a way that makes them readable?
sorry if this is insanely ignorant

it's a way of writing callbacks without writing callbacks

the first "writing" means: causing code to be generated into a real world executable and later executed by a real world CPU
the second "writing" means: putting text in an editor

in other words it's something that could be given the odious name of "syntactic sugar"

what await does behind the curtain is:
  • save the code position right after the awaited expression evaluation
  • pass a compiler-generated callback and the saved state (local variables plus the saved position) to the asynchronous function
  • return to the caller of the resumable function
when the asynchronous function completes, it calls the compiler-generated callback passing it the result (or error) and the saved state. the callback copies the result (or error) to some local variable of the resumable function, and resumes it from the saved position (how it works in Real Code terms: when you write a resumable function, what the compiler actually writes for you is some kind of class that encapsulates the frame of the function, with an instance variable for each local variable and special variables to save the point of execution to resume from; the code of the resumable function will be a method of this class, the "saved state" will be a pointer to an instance of the class, and the callback or callbacks will be static methods that set the "this" pointer to the saved state, and jump to the saved position)

so. the asynchronous function does take a callback, but the compiler writes the callback for you. what the callback does is the most useful thing a callback could do in an imperative language: resume execution from a specific point. callbacks, nested functions, blocks, lambdas, etc. are poor substitutes of just saving a position within an invocation of a function, and then jumping back to it

callbacks become invisible, nothing breaks the flow of your code: your code gets as close as possible to its synchronous, blocking equivalent. in imperative languages, whatever breaks the flow of code breaks all of your tools: debugging breaks, exception handling breaks, resource ownership breaks. await-based code can conceivably be single-stepped in the debugger (as long as the debugger knows about resumable functions, then it can accept single-step breakpoints firing in the "wrong" thread if the thread is executing the right instance of the right resumable function), unlike callback-based code where you have to manually set breakpoints at the beginning of the callback, because there is no way the debugger could ever know the callback is even related to the rest of the code, much less that it's a continuation

hackbunny fucked around with this message at 03:59 on Nov 10, 2014

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

pseudorandom name posted:

hint: C++ is garbage and the people in charge of the specification live in ivory towers

not anymore, C++0x started a loving renaissance. I can't think of a single feature introduced by C++11 or C++14 that isn't massively useful and very welcome and very belated

Mr. Glass
May 1, 2009
the only problem with c++0x is that it didn't delete the 95% of c++ that is complete garbage

pseudorandom name
May 6, 2007

Mr. Glass posted:

the only problem with c++0x is that it didn't delete the 95% of c++ that is complete garbage

aka templates

sarehu
Apr 20, 2007

(call/cc call/cc)
Monads don't really work in languages other than Haskell because other languages don't have purity.

And webdevs gush over promises because it took them 17 years to reinvent them.

The best way to do single threaded event looping in C++ is cooperative userland threads, sorry.

There's a lot of variable in the quality and convenience of callback usage in C++. You can structure callbacks a little bit better than dumb naive callback-having.

MononcQc
May 29, 2007

hackbunny posted:

the only thing that seems to help is state machines. explicit, old school state machines. define an enum with a list of states. an instance variable with the current state. (push) events are modeled as public methods or notification observers. all entry points are wrapped with code that stabilizes the state first, for example generates pull events, and warns/faults on re-entry (re-entry is the devil, re-entry is an evil spell that conjures race conditions in single-threaded code). why pull events you ask, because not all data is encapsulated I answer, some comes from other components, that I try not to observe too closely: you don't want to chase every single mutation, especially because they are rarely transactional (mine are, but who else's? no class is an island). relationships between components cannot be formalized too hard, because requirements change and then I look like a fool

State machines are fun in languages where you have tail call optimization. Rather than using enums, I can design my states as functions:
code:
off() ->
    case poll_event() of
        click -> on();  % if the event is 'click' become 'on'
        _ -> off()      % if the event is anything else, stay 'off'
    end.

on() ->
    case poll_event() of
        click -> off();
        _ -> on()
    end.

main() ->
    %% Start in the 'off' state.
    off().
Of course you may want to make it declarative. So what you do is use higher order functions and abstract away all the poll-then-react dance:

code:
poll_loop(State) -> poll_loop(State(poll_event())).

on(click) -> fun off/1; % return the function 'off'
on(_) -> fun on/1.      % return the current function

off(click) -> fun on/1;
off(_) -> fun off/1.

main() ->
    poll_loop(fun off/1).
There you go, declarative FSM. Of course if you hate the syntax for anonymous functions, hide it away in the event loop with dynamic calls. The advantage is that your FSM is now possible to reason about in a purely data-driven manner:


code:
poll_loop(State) -> poll_loop(call(State, [poll_event()])).

on(click) -> off;
on(_) -> on. 

off(click) -> on;
off(_) -> off.

main() ->
    poll_loop(off).
Then again, you know common lisp so you can probably see that code being replicated there easily. The Erlang atoms become lisp symbols, and who needs enums anymore then.

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

MononcQc posted:

State machines are fun in languages where you have tail call optimization. Rather than using enums, I can design my states as functions:
code:
off() ->
    case poll_event() of
        click -> on();  % if the event is 'click' become 'on'
        _ -> off()      % if the event is anything else, stay 'off'
    end.

on() ->
    case poll_event() of
        click -> off();
        _ -> on()
    end.

main() ->
    %% Start in the 'off' state.
    off().
Of course you may want to make it declarative. So what you do is use higher order functions and abstract away all the poll-then-react dance:

code:
poll_loop(State) -> poll_loop(State(poll_event())).

on(click) -> fun off/1; % return the function 'off'
on(_) -> fun on/1.      % return the current function

off(click) -> fun on/1;
off(_) -> fun off/1.

main() ->
    poll_loop(fun off/1).
There you go, declarative FSM. Of course if you hate the syntax for anonymous functions, hide it away in the event loop with dynamic calls. The advantage is that your FSM is now possible to reason about in a purely data-driven manner:


code:
poll_loop(State) -> poll_loop(call(State, [poll_event()])).

on(click) -> off;
on(_) -> on. 

off(click) -> on;
off(_) -> off.

main() ->
    poll_loop(off).
Then again, you know common lisp so you can probably see that code being replicated there easily. The Erlang atoms become lisp symbols, and who needs enums anymore then.

i like elm's model of frp for stuff like this:

code:
update : Input -> State -> State
update input state =
    case input of
        Click -> if state == On then Off else On
        _ -> Off

events : Signal Input

-- foldp : (a -> b -> b) -> b -> Signal a -> Signal b
-- it's a built in that's sort of a fold, but for time varying values instead of lists
main = foldp update Off events

DONT THREAD ON ME
Oct 1, 2002

by Nyc_Tattoo
Floss Finder

fart simpson posted:

a monad is a monoid in the category of endofunctors

jfc thanks, i get it now

redleader
Aug 18, 2005

Engage according to operational parameters
eric lippert's monad series is a pretty readable introduction to monads in a more familiar language. between this and the last six pages of monad chat, i think i'm finally starting to grasp the concept.

not that knowing that a monad is a monoid in etc etc is of any real use to me, since all the useful monads come bundled up with some pleasant syntax in c#

my homie dhall
Dec 9, 2010

honey, oh please, it's just a machine

redleader posted:

eric lippert's monad series is a pretty readable introduction to monads in a more familiar language. between this and the last six pages of monad chat, i think i'm finally starting to grasp the concept.

not that knowing that a monad is a monoid in etc etc is of any real use to me, since all the useful monads come bundled up with some pleasant syntax in c#

a 13-part series to 'understanding' monads

l

o

l

fart simpson
Jul 2, 2005

DEATH TO AMERICA
:xickos:

thats only 1 part for each page of monadchat in this thread

hackbunny
Jul 22, 2007

I haven't been on SA for years but the person who gave me my previous av as a joke felt guilty for doing so and decided to get me a non-shitty av

MononcQc posted:

and who needs enums anymore then.

<- the Objective C programmer

seriously though, I think I could use this. I will hate myself when I have to debug it, months down the line, and it would mean I'd have to design before writing code, but I could use this

MononcQc
May 29, 2007

hackbunny posted:

<- the Objective C programmer

seriously though, I think I could use this. I will hate myself when I have to debug it, months down the line, and it would mean I'd have to design before writing code, but I could use this

Well depending on the form, you can end up adding debug info to your main loop: store the last sequence of transitions or of events in a circular buffer, trigger things to print it out directly, etc. or even just submit custom functions that can operate on your FSM state. This stuff can then be switched on and off at run time, per-FSM, as needed.

If you make that loop generic, it can be reused (with all the debugging code included) for all your other FSMs and just have that one core to maintain.

I'm cheating a bit here because I'm slowly talking you into translating OTP's generic FSM mechanism in your language of choice.

Shaggar
Apr 26, 2006
monads are a fork bomb for programming discussion.

Sweevo
Nov 8, 2007

i sometimes throw cables away

i mean straight into the bin without spending 10+ years in the box of might-come-in-handy-someday first

im a fucking monster

functional programming languages are like dvorak keyboards - once you start using them you become incapable of talking about anything else

Jonny 290
May 5, 2005



[ASK] me about OS/2 Warp

Shaggar posted:

monads are a fork bomb for programming discussion.

they need to hurry the gently caress up and post some cats then

Mr. Glass
May 1, 2009

surprisingly templates are not the most awful feature of c++

tef
May 30, 2004

-> some l-system crap ->

hackbunny posted:

the only thing that seems to help is state machines. explicit, old school state machines.

when i'm not writing api boilerplate i am writing state machines. so many goddam state machines.

thankfully most of them are mostly acyclic, but every so often i have to bust out the trampoline.

quote:

define an enum with a list of states. an instance variable with the current state. (push) events are modeled as public methods or notification observers.

that is just one way of doing it. in less C like languages i tend to have a wrapper containing a set of objects to delegate to and a handful of wrapper methods that do trampolining.

Cybernetic Vermin
Apr 18, 2005

number the n states, create a sparse nxn boolean matrix for each alphabet symbol, and a vector with the initial state set, multiply away~~

Bloody
Mar 3, 2013

I write alot of state machines but usually in verilog, which is a bad language but less bad than vhdl.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip
it took me a while to realize you don't actually have to yell all the time in vhdl :shobon:

sarehu
Apr 20, 2007

(call/cc call/cc)
But I like yelling (in both VHDL and SQL).

Adbot
ADBOT LOVES YOU

Gul Banana
Nov 28, 2003

hackbunny posted:

monads specifically I don't know but I see a lot of unwarranted gushing over futures/promises. which are poo poo, I've used them when they were called OVERLAPPED and when they were called struct aiocb and when they were called IAsyncResult and they always always sucked. we use them because we have no choice, dressing them up with a next() method doesn't make them smell less

did you use them when they were called Task<T>? because that's the monadic version and is a lot nicer than its predecessors

async/await is nicer still, however. specialised language features generally are

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply