Recent

Author Topic: How to assign an anonymous function  (Read 4585 times)

Pluto

  • New Member
  • *
  • Posts: 29
How to assign an anonymous function
« on: March 28, 2021, 07:36:15 pm »
I'm waiting for that ah-ha moment when I can start to figure out really simple things.... Every piece of documentation I can find seems to say this should work, yet I get a compilation error.  I feel dumb for asking, but why doesn't this work?  Is there some compiler directive I have to give to let this thing do anonymous functions?


var
  myFilterFunction:function(s:String):boolean;

begin
  writeln('test harness');
  myFilterFunction:=function(s:String):boolean  { this is line 17 }
    begin
      result:=s.StartsWith('t');
    end;
  readln();
end.


Compile Project, Target: MyTestProject.exe: Exit code 1, Errors: 2
MyTestsProject.lpr(17,21) Error: Illegal expression
MyTestsProject.lpr(17,29) Fatal: Syntax error, ";" expected but "(" found
« Last Edit: March 28, 2021, 07:42:18 pm by Pluto »

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: How to assign an anonymous function
« Reply #1 on: March 28, 2021, 07:49:05 pm »
IIRC, that construction is how they will work, but it isn't yet done. Unless it's in trunk, which I don't know ... :-[
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #2 on: March 28, 2021, 08:05:21 pm »
Thanks for the quick responses...For context I'm trying to use some of those great functions in TStrings for manipulating data (like filter())... Hoping to find a more general-purpose library using generics... ;)

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #3 on: March 28, 2021, 08:50:53 pm »
Well, I'm coming from languages where I haven't written a for-loop in years (Edit: slight exaggeration).  Things like DLINQ (C#) and Streams API (Java) relegate the looping to the base API.  The advantage of that is three-fold... (1) It cuts the amount of code you need to write in half, (2) it produces a more declarative syntax that is easier to read and understand, and (3) it allows the API to handle the parallelization, so you get it for-free, rather than having to write it yourself with async/await (or worse, spawning threads)...

But its a paradigm shift that requires an easy way to parameterize functions...  The library itself would be fairly easy to write, because we could just imitate the Java library...

I didn't quite understand what you said about Generics, Jamie.  Are you saying Generics actually replicates user's code at compile time?
« Last Edit: March 28, 2021, 08:54:06 pm by Pluto »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: How to assign an anonymous function
« Reply #4 on: March 28, 2021, 09:13:28 pm »
This library offers the use of filters, maps, foldings and other functions. Although, in the absence of anonymous functions, this is not so convenient.
Honestly, I'd like to believe that the problem of code bloat when using generics is outweighed by simpler code reuse.

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9864
  • Debugger - SynEdit - and more
    • wiki
Re: How to assign an anonymous function
« Reply #5 on: March 28, 2021, 10:06:27 pm »
Well you can write functions like: map, filter, sort, ...

In fact some do already exist: TStringList.CustomSort()

But, you can not write the "helper function" (e.g. compare for sort) on the fly.
You have to declare it upfront.

And also when you write your sort, you have to decide what kind of "function" it accepts.
This is not about the function arguments, which obviously must match.
This is about:
- plain function: "function Foo(); begin end"
- Method (of a class): "function TMyClass.Foo; begin end"
- Nested functions: Afaik needs a special modeswitch.
They all have different signatures, and are not assignment compatible.

You also do not have closures (not the same as anonymous functions / even though a lot of languages only offer the two as one bundled package).


But there is one good thing as well.

generic functions.

You can write a sort function as a generic, and then specialize it  (afaik possible on the fly) for any type (int, real, string, even class).
However, only if the operators are available or overloaded. => If you use > and < then those must be available for whatever type you want to compare.

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #6 on: March 28, 2021, 10:35:54 pm »
This is all good stuff, but the magic happens in the parameterization of the function...  Would love to implement anonymous functions (and even lamda), but it might be above my head.  Edit: maybe I'll see if I can pull the free pascal source and try to understand how that would be done...
« Last Edit: March 28, 2021, 10:37:28 pm by Pluto »

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #7 on: March 28, 2021, 10:47:09 pm »
Meh.  Maybe I'm overthinking it... I tend to do that.  For a good introductory article on the streaming api (other than his for-loop examples being incomplete), see https://blog.jdriven.com/2019/10/loop

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to assign an anonymous function
« Reply #8 on: March 28, 2021, 11:47:08 pm »
Did I get his last example right?

The author seems to believe this code is unreadable and will cause problems a few months down the road:
Code: Java  [Select][+][-]
  1.   for (Person p : persons) {
  2.         for (Person sibling : p.getSiblings()) {
  3.             if (
  4.                sibling.getGender().equals("M") &&
  5.                sibling.getAge() > 18 &&
  6.                sibling.getAge() <= 65 &&
  7.                sibling.getName() != null &&
  8.                sibling.getName().startsWith("B")) {
  9.                 result.add(sibling.getName());
  10.             }
  11.         }
  12.     }

While, according to the author, this one is the perfect solution:
Code: Java  [Select][+][-]
  1.   List<String> result = persons.stream()
  2.           .flatMap(p -> p.getSiblings().stream())
  3.           .filter(p -> p.getGender().equals("M"))
  4.           .filter(p -> p.getAge() > 18)
  5.           .filter(p -> p.getAge() <= 65)
  6.           .filter(p -> p.getName() != null)
  7.           .filter(p -> p.getName().startsWith("B"))
  8.           .map(p -> p.getName())
  9.           .collect(Collectors.toList());

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #9 on: March 29, 2021, 02:57:33 am »
The author seems to believe this code is unreadable and will cause problems a few months down the road:

Did I mention that sometimes I over-think things?

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to assign an anonymous function
« Reply #10 on: March 29, 2021, 03:24:31 am »
The author seems to believe this code is unreadable and will cause problems a few months down the road:

Did I mention that sometimes I over-think things?

Yes, but I mean no, I was not talking about you. It is the blog post you linked to. I found it odd that the writer of that blog post did not notice how by only changing the formatting of the code, how this alone,  makes both approaches almost identical.

egsuh

  • Hero Member
  • *****
  • Posts: 1289
Re: How to assign an anonymous function
« Reply #11 on: March 29, 2021, 04:41:17 am »
I've seen many questions on anynymous functions. I've done some programming in javascript, and think that anonymous functions are most similar to subroutines within subroutines. Pascal still needs name of the subroutine. --- nonymous. 

Code: Pascal  [Select][+][-]
  1. procedure ......
  2. var
  3.    anyvar: variant;
  4.  
  5.    function  myFilterFunction (s:String):boolean;
  6.     begin
  7.       result:=s.StartsWith('t');
  8.     end;
  9.  
  10. begin
  11.   writeln('test harness');
  12.   myFilterFunction;
  13.   readln();
  14. end.
  15.  


Regarding "for" statements, I would write as follows (not every construct will support for... in):

Code: Pascal  [Select][+][-]
  1. for p in persons do
  2.    with p do begin
  3.         if Gender <> 'M'  then continue;
  4.         if Age <= 18  then continue;
  5.         if Age > 65   then continue;
  6.         if Name = ''  then continue;
  7.  
  8.         List.Add(p);
  9. end;

I'd rather have something like

            if MoutineHeight in [15000, 20000..40000, >90000] then...   

etc.
« Last Edit: March 29, 2021, 05:33:54 am by egsuh »

Pluto

  • New Member
  • *
  • Posts: 29
Re: How to assign an anonymous function
« Reply #12 on: March 29, 2021, 05:13:30 am »
...And when someone comes to a language from another language, they carry a lot of preconceived notions, whether they realize it or not...  And so it takes them time to acclimate and fully understand the implications of how things are done... egsuh makes a very good implicit point that Pascal's superior math and underlying set theory provides some alternatives that I wasn't even considering...

avk

  • Hero Member
  • *****
  • Posts: 752
Re: How to assign an anonymous function
« Reply #13 on: March 29, 2021, 05:41:45 am »
Did I get his last example right?

The author seems to believe this code is unreadable and will cause problems a few months down the road...

Well, yes, as usual hype, but sometimes it's funny.
For example, how would you solve such a problem?

Let Memo1 contain a list of words(just ASCII for simplicity) separated by tabs, spaces, commas, semicolons, or just line breaks.
When Button1 is pressed, it is required to split this list into words, convert these words to lower case and display in Memo1 non-repeating words consisting of three or more characters and which are palindromes(in lexicographic order, each word on a separate line), or display a message that there are no palindromes.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: How to assign an anonymous function
« Reply #14 on: March 29, 2021, 06:04:04 am »
Code: Pascal  [Select][+][-]
  1.         if Gender <> 'M'  then continue;
  2.         if Age <= 18  then continue;
  3.         if Age > 65   then continue;
  4.         if Name = ''  then continue;

Why would you do the conditions this way? I would have expected something along:
Code: Pascal  [Select][+][-]
  1.      if (Gender = 'M') and
  2.         (Age > 18)  and
  3.         (Age <= 65)   and
  4.         (Name <> '')  then
  5.  

What did I miss?

 

TinyPortal © 2005-2018