Recent

Author Topic: Functional programming in Pascal  (Read 24869 times)

440bx

  • Hero Member
  • *****
  • Posts: 4014
Re: Functional programming in Pascal
« Reply #60 on: July 03, 2019, 03:56:56 pm »
... pass the pointer plus the state (together a "function reference") to some outer scope.
scope level jumping/referencing... isn't that the very essence of spaghetti code ?  (not even taking into account the difference timing in variable capture can make.)

I think it's fine and, sometimes even desirable, to have a way to define and use function/procedures inline but, letting references to them leak out of the scope they are defined in, not even Italians make spaghetti that jumps from one plate to another.

It seems to me that, lambas - as currently implemented - are an idea/method, from someone who coded themselves into a corner, who needed someway to get themselves out of the mess they made.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Functional programming in Pascal
« Reply #61 on: July 04, 2019, 12:42:43 am »
The main use for the state is that you can use it to reference external stuff, like sockets. But their state tends to change over time, so don't wait too long with executing them.

Otherwise, it is far simpler to execute it immediately and return the result.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5462
  • Compiler Developer
Re: Functional programming in Pascal
« Reply #62 on: July 04, 2019, 09:25:19 am »
I hope I understood this feature, please correct me if not.
Yes, you understood it correctly. And yes, the D is essentially the state of the function reference.

... pass the pointer plus the state (together a "function reference") to some outer scope.
scope level jumping/referencing... isn't that the very essence of spaghetti code ?  (not even taking into account the difference timing in variable capture can make.)

I think it's fine and, sometimes even desirable, to have a way to define and use function/procedures inline but, letting references to them leak out of the scope they are defined in, not even Italians make spaghetti that jumps from one plate to another.

It seems to me that, lambas - as currently implemented - are an idea/method, from someone who coded themselves into a corner, who needed someway to get themselves out of the mess they made.
They allow you for example to easily set up a thread without the need to declare a whole class:
Code: Pascal  [Select][+][-]
  1. procedure DoSomethingAsynchronous(aObj: TMyWorkObject; aEvent: TEvent);
  2. begin
  3.   TThread.CreateAnonymousThread(procedure
  4.     begin
  5.       DoSomethingWithWorkObject(aObj);
  6.       aEvent.SetEvent;
  7.     end);
  8. end;
At work - where we use C++ - I use their C++ equivalent very much, because they essentially allow to keep code together that conceptually belongs together (though more often than not I also use them, because C++ does not know nested functions  :-[ )

440bx

  • Hero Member
  • *****
  • Posts: 4014
Re: Functional programming in Pascal
« Reply #63 on: July 04, 2019, 12:02:30 pm »
They allow you for example to easily set up a thread without the need to declare a whole class:
Code: Pascal  [Select][+][-]
  1. procedure DoSomethingAsynchronous(aObj: TMyWorkObject; aEvent: TEvent);
  2. begin
  3.   TThread.CreateAnonymousThread(procedure
  4.     begin
  5.       DoSomethingWithWorkObject(aObj);
  6.       aEvent.SetEvent;
  7.     end);
  8. end;
At work - where we use C++ - I use their C++ equivalent very much, because they essentially allow to keep code together that conceptually belongs together (though more often than not I also use them, because C++ does not know nested functions  :-[ )
There is no doubt there are cases, like the example you presented, where that syntax results in something that is clean and easier to maintain than the traditional alternative but, it also opens the door to some rather "poor" constructions. 

I think the fact the C/C++ doesn't know nested functions is one of the primary reasons for their use. Often in ways, I find "questionable"  (to put it kindly.)

Thank you for the example.  It's a nice one.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5462
  • Compiler Developer
Re: Functional programming in Pascal
« Reply #64 on: July 05, 2019, 09:36:26 am »
There is no doubt there are cases, like the example you presented, where that syntax results in something that is clean and easier to maintain than the traditional alternative but, it also opens the door to some rather "poor" constructions.
Any feature opens the door for "poor" constructions. Anonymous functions aren't anything special there. If a feature exists it's going to be abused.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11445
  • FPC developer.
Re: Functional programming in Pascal
« Reply #65 on: July 05, 2019, 10:21:18 am »
Most uses of anonymous methods are in cross thread usage, where nested functions wouldn't work anyway.


SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Functional programming in Pascal
« Reply #66 on: July 05, 2019, 01:02:19 pm »
How do you track which threads are still active, and how do you distribute the pointers?

440bx

  • Hero Member
  • *****
  • Posts: 4014
Re: Functional programming in Pascal
« Reply #67 on: July 05, 2019, 01:22:40 pm »
Any feature opens the door for "poor" constructions. Anonymous functions aren't anything special there. If a feature exists it's going to be abused.
Yes, that is true but, some constructions lend themselves much better for building atrocities than others.  Lambdas are among them.  The only example I've seen of a nice use of a lambda I can think of, is the one you gave in this thread.  The other uses I've seen go from "I can do that just as cleanly and easily without a lambda" to "another sample of logical epilepsy".

That said, there is one thing I do like about them, that is, it's inline (don't have to go some other place in the source to find out what the thing does.)



(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11445
  • FPC developer.
Re: Functional programming in Pascal
« Reply #68 on: July 05, 2019, 01:37:22 pm »
How do you track which threads are still active, and how do you distribute the pointers?

I don't do neither, but have to admit I don't entirely understand what you mean by that.

I have a bunch of threads for odd jobs. (two worker threads for light things, and two threads for storing images(*)). Most of synchronizing goes from the threads that do the actual work to the main loop. Mostly for gui, but some state is kept in the mainthread because the gui makes the most complex use of them.

More regular work goes over queues (only queueing a method that drains the queue), but less common work goes via anonymous methods to avoid having to setup object types and queues etc for them.

IOW I never create threads for such things, I always signal a worker thread that is blocked on a tevent, or the mainthread that handles it as part of the message loop.


(*) mostly to mask latency due to when directories are relatively full, directory housekeeping can stall a write for a second

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Functional programming in Pascal
« Reply #69 on: July 05, 2019, 02:54:51 pm »
So, you have multiple threads and a queue, the threads do their thing and when they are done, they call a synced method in the main prog, after which they try to read the next job from the queue?

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11445
  • FPC developer.
Re: Functional programming in Pascal
« Reply #70 on: July 05, 2019, 04:05:24 pm »
So, you have multiple threads and a queue, the threads do their thing and when they are done, they call a synced method in the main prog, after which they try to read the next job from the queue?

Yes and no, the mainthread is not the initiator of everything.  Cameras and threads monitoring connections (serial or network) also generate events that feed queues.

But yes, many queues are basic producer/consumers using queues.  Most of these queues have pools and factories attached to them. So if you ask the queue for an empty item, it checks the pool if there are unused items in there and then recycles them, or asks the factory to create them otherwise.

Some of the items in the queues are manually reference counted. The queue-pool-factories complex are (each) generic, and there is a derived form of the generic that handles the base refcounting.

Some threads are fed by a queue also have a tevent that must be signaled to unblock the thread and inspect the queue.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Functional programming in Pascal
« Reply #71 on: July 05, 2019, 04:45:42 pm »
Are there standard components for that? It's always a lot of work to build.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11445
  • FPC developer.
Re: Functional programming in Pascal
« Reply #72 on: July 05, 2019, 05:07:49 pm »
Are there standard components for that? It's always a lot of work to build.

No, but the base pool-factory unit is maybe 400 lines. IIRC it is even my opengl demonstration software. (https://forum.lazarus.freepascal.org/index.php/topic,30556.msg194484.html#msg194484).

While I'm allowed to distribute parts of that. (my boss is luckily a realistic about the more "utility" units), it is a bit entangled with the framework, so I can't just copy something compilable from there.

Note that I simply use tthreadlist as base for most queues and pools. For moderate use that is no problem, but if you go to very high amounts of messages passed that might hurt.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1313
Re: Functional programming in Pascal
« Reply #73 on: July 05, 2019, 05:54:10 pm »
Thanks, I take a look.

First I used sockets, but that's a lot of overhead. Then a concurrent queue, but it is still hard to track which threads are alive. Then again, I rarely use a pool, I just create one when I need it.

I prefer a few queues, one for new jobs and one for feedback, but that way you cannot check if a thread is still alive. And with jobs, I tend to have a lot of different ones after a while.

mr-highball

  • Full Member
  • ***
  • Posts: 233
    • Highball Github
Re: Functional programming in Pascal
« Reply #74 on: August 01, 2019, 05:12:07 pm »
I'm a bit late to this topic  :-[....
But, ezthreads allows for the use of nested procs/standard procs/object procs, is reference counted, captures variables, and offers Await functionality for a single thread/group of threads/all threads which I believe should be able to be used for the OP's original requests without requiring a lambda implementation.

here's a simple "hello world" sample pulled from my tester app
https://github.com/mr-highball/ezthreads/blob/master/test/ezthreads_tester.lpr#L88

Code: Pascal  [Select][+][-]
  1. (*
  2.   a "hello world" of sorts. shows a fairly complete demonstration
  3.   of creating a thread to write hello world to the console
  4. *)
  5. procedure TestHelloWorld;
  6. const
  7.   NAME='hi';
  8. var
  9.   Thread : IEZThread;
  10.  
  11.   procedure Start(Const AThread:IEZThread);
  12.   begin
  13.     WriteLn(AThread[NAME]);
  14.   end;
  15.  
  16. begin
  17.   Thread:=TEZThreadImpl.Create;
  18.  
  19.   Thread
  20.     .AddArg(NAME,'TestHelloWorld::hello world from an ezthread!')
  21.     .Setup(Start)
  22.     .Start;
  23.  
  24.   Await;
  25.  
  26.   WriteLn('TestHelloWorld::success, waiting no longer');
  27. end;
  28.  

 

TinyPortal © 2005-2018