Rocksolid Light

Welcome to RetroBBS

mail  files  register  newsreader  groups  login

Message-ID:  

I am not an Economist. I am an honest man! -- Paul McCracken


devel / comp.lang.ada / project euler 26

SubjectAuthor
* project euler 26CSYH (QAQ)
+* Re: project euler 26Niklas Holsti
|`* Re: project euler 26Dmitry A. Kazakov
| `* Re: project euler 26Ben Bacarisse
|  `* Re: project euler 26Dmitry A. Kazakov
|   `* Re: project euler 26Ben Bacarisse
|    `* Re: project euler 26Dmitry A. Kazakov
|     `* Re: project euler 26Ben Bacarisse
|      `* Re: project euler 26Dmitry A. Kazakov
|       +* Re: project euler 26Ben Bacarisse
|       |`* Re: project euler 26Dmitry A. Kazakov
|       | `* Re: project euler 26Ben Bacarisse
|       |  `* Re: project euler 26Dmitry A. Kazakov
|       |   `* Re: project euler 26Ben Bacarisse
|       |    `* Re: project euler 26Dmitry A. Kazakov
|       |     `* Re: project euler 26Ben Bacarisse
|       |      +* Re: project euler 26Dmitry A. Kazakov
|       |      |`* Re: project euler 26Ben Bacarisse
|       |      | `* Re: project euler 26Dmitry A. Kazakov
|       |      |  `* Re: project euler 26Ben Bacarisse
|       |      |   `* Re: project euler 26Dmitry A. Kazakov
|       |      |    `* Re: project euler 26Ben Bacarisse
|       |      |     `* Re: project euler 26Dmitry A. Kazakov
|       |      |      `* Re: project euler 26Ben Bacarisse
|       |      |       `* Re: project euler 26Dmitry A. Kazakov
|       |      |        `* Re: project euler 26Ben Bacarisse
|       |      |         `* Re: project euler 26Dmitry A. Kazakov
|       |      |          `* Re: project euler 26Ben Bacarisse
|       |      |           `* Re: project euler 26Dmitry A. Kazakov
|       |      |            `- Re: project euler 26Ben Bacarisse
|       |      `* Re: project euler 26G.B.
|       |       `* Re: project euler 26Ben Bacarisse
|       |        `* Re: project euler 26G.B.
|       |         +- Re: project euler 26Ben Bacarisse
|       |         `- Re: project euler 26Dmitry A. Kazakov
|       `- Re: project euler 26moi
+- Re: project euler 26Dmitry A. Kazakov
`* Re: project euler 26Francesc Rocher
 `- Re: project euler 26CSYH (QAQ)

Pages:12
project euler 26

<c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9988&group=comp.lang.ada#9988

  copy link   Newsgroups: comp.lang.ada
X-Received: by 2002:a05:620a:3f48:b0:76d:72dc:700 with SMTP id ty8-20020a05620a3f4800b0076d72dc0700mr194335qkn.10.1693819192410;
Mon, 04 Sep 2023 02:19:52 -0700 (PDT)
X-Received: by 2002:a17:902:ec81:b0:1c2:c60:8384 with SMTP id
x1-20020a170902ec8100b001c20c608384mr3611622plg.7.1693819191863; Mon, 04 Sep
2023 02:19:51 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer03.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.ada
Date: Mon, 4 Sep 2023 02:19:51 -0700 (PDT)
Injection-Info: google-groups.googlegroups.com; posting-host=54.199.241.6; posting-account=fZvo4QoAAABi0pYBrtK7uR0nkDKUP_JT
NNTP-Posting-Host: 54.199.241.6
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
Subject: project euler 26
From: schen309@asu.edu (CSYH (QAQ))
Injection-Date: Mon, 04 Sep 2023 09:19:52 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1068
 by: CSYH (QAQ) - Mon, 4 Sep 2023 09:19 UTC

I am new to Ada, I know is there a good way to start this program?
thanks
https://projecteuler.net/problem=26

Re: project euler 26

<klls16F37qbU1@mid.individual.net>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9989&group=comp.lang.ada#9989

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!weretis.net!feeder8.news.weretis.net!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From: niklas.holsti@tidorum.invalid (Niklas Holsti)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 4 Sep 2023 14:06:13 +0300
Organization: Tidorum Ltd
Lines: 15
Message-ID: <klls16F37qbU1@mid.individual.net>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
X-Trace: individual.net X4M1AE7izSoaH/dXkYBMQQB/bRdQQN6ZccEnC1C9mCG8sgZC1o
Cancel-Lock: sha1:8N4TV7AhdC4BdAvWZ0xw7uvnt80= sha256:xRLkTFp9qE39hUNFCMeYMzE/cUKfejWcOIFRle5PJOI=
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:102.0)
Gecko/20100101 Thunderbird/102.12.0
Content-Language: en-US
In-Reply-To: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
 by: Niklas Holsti - Mon, 4 Sep 2023 11:06 UTC

On 2023-09-04 12:19, CSYH (QAQ) wrote:
> I am new to Ada, I know is there a good way to start this program?
> thanks
> https://projecteuler.net/problem=26

First invent/discover the method (algorithm) for solving the problem,
without thinking about the programming language.

I don't think any language has built-in features that would lead to a
direct solution, although some functional language with lazy evaluation
could come close, because such languages can manipulate unbounded
(potentially infinite) sequences of values. Such sequences can be
handled in Ada, too, but with more effort -- they are not "built in" to Ada.

Re: project euler 26

<ud4j5l$1fo57$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9990&group=comp.lang.ada#9990

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 4 Sep 2023 14:39:17 +0200
Organization: A noiseless patient Spider
Lines: 36
Message-ID: <ud4j5l$1fo57$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 4 Sep 2023 12:39:17 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="84abbd2dc2e4fea6082302e85e06124d";
logging-data="1564839"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1//w6Gcd/lJIoagYaPZf8iG/H+vPh+9tak="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:/9g+4rsVnV3lc7Xa6aiPODtA2KA=
Content-Language: en-US
In-Reply-To: <klls16F37qbU1@mid.individual.net>
 by: Dmitry A. Kazakov - Mon, 4 Sep 2023 12:39 UTC

On 2023-09-04 13:06, Niklas Holsti wrote:
> On 2023-09-04 12:19, CSYH (QAQ) wrote:
>> I am new to Ada, I know is there a good way to start this program?
>> thanks
>> https://projecteuler.net/problem=26
>
> First invent/discover the method (algorithm) for solving the problem,
> without thinking about the programming language.
>
> I don't think any language has built-in features that would lead to a
> direct solution, although some functional language with lazy evaluation
> could come close, because such languages can manipulate unbounded
> (potentially infinite) sequences of values. Such sequences can be
> handled in Ada, too, but with more effort -- they are not "built in" to
> Ada.

Infinite division does not require big numbers, which Ada 22 has, but I
wound not use them anyway because the performance would be abysmal.

BTW, Ada is perfect for numeric algorithms no need to resort to
functional mess... (:-))

The problem itself requires as you said mathematical analysis, because a
naive method of comparing partial division result with itself is
obviously wrong. E.g. let you have

0.12341234...

you could not conclude that the period is (1234) because it could
actually be (123412345).

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<ud4p9q$1gnj3$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9991&group=comp.lang.ada#9991

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 4 Sep 2023 16:23:54 +0200
Organization: A noiseless patient Spider
Lines: 84
Message-ID: <ud4p9q$1gnj3$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 4 Sep 2023 14:23:54 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="84abbd2dc2e4fea6082302e85e06124d";
logging-data="1597027"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19SyZPw/eTT+M4wWtadMRTu5rPMnBB11Do="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:UeQia4wcDxvTGSHH8VNeLkDFUvo=
In-Reply-To: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
Content-Language: en-US
 by: Dmitry A. Kazakov - Mon, 4 Sep 2023 14:23 UTC

On 2023-09-04 11:19, CSYH (QAQ) wrote:
> I am new to Ada, I know is there a good way to start this program?
> thanks
> https://projecteuler.net/problem=26

Ok, I leave it to you checking if my implementation is correct.
-------------------test.adb----------
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;

procedure Test is

N : constant := 1000;

function Period (Divisor : Positive) return String is
type Remainder is record
Index : Positive;
Value : Positive;
end record;
Result : String (1..N);
Value : Integer := 1;
Remainders : array (1..N) of Remainder;
begin
for Index in Result'Range loop
Value := Value * 10;
Result (Index) :=
Character'Val (Character'Pos ('0') + Value / Divisor);
Value := Value mod Divisor;
if Value = 0 then
return ""; -- Non-periodic
end if;
if Index > 1 then
for Item in 1..Index - 1 loop
declare
This : Remainder renames Remainders (Item);
begin
if Value = This.Value then
return Result (This.Index + 1..Index);
end if;
end;
end loop;
end if;
Remainders (Index) := (Index, Value);
end loop;
raise Constraint_Error with "Period calculation error";
end Period;

Max_Period : Unbounded_String;
Max_Divisor : Positive;
begin
for Divisor in 2..999 loop
declare
This : constant String := Period (Divisor);
begin
if This /= "" then
Put_Line
( "1 /"
& Integer'Image (Divisor)
& " has "
& This
& " in period"
);
end if;
if Length (Max_Period) < This'Length then
Max_Period := To_Unbounded_String (This);
Max_Divisor := Divisor;
end if;
end;
end loop;
Put_Line
( "The first longest period is "
& To_String (Max_Period)
& " in 1 /"
& Integer'Image (Max_Divisor)
);
end Test;
-------------------test.adb----------
It gives the longest period for 1/983.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<878r9mudvj.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9992&group=comp.lang.ada#9992

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 04 Sep 2023 17:01:04 +0100
Organization: A noiseless patient Spider
Lines: 38
Message-ID: <878r9mudvj.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="e2cb716c5442438ebe9264e332ee95d9";
logging-data="1627475"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/0li7nHnLEANnMakgnsLh9DoNQskUnoBw="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:0zb1ocrDBOVgXvwdOm59plppnXg=
sha1:l/oTWclUlbjJ7CKT88CTwII8foU=
X-BSB-Auth: 1.9b27877351d9e45f752c.20230904170104BST.878r9mudvj.fsf@bsb.me.uk
 by: Ben Bacarisse - Mon, 4 Sep 2023 16:01 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-04 13:06, Niklas Holsti wrote:
>> On 2023-09-04 12:19, CSYH (QAQ) wrote:
>>> I am new to Ada, I know is there a good way to start this program?
>>> thanks
>>> https://projecteuler.net/problem=26
>> First invent/discover the method (algorithm) for solving the problem,
>> without thinking about the programming language.
>> I don't think any language has built-in features that would lead to a
>> direct solution, although some functional language with lazy evaluation
>> could come close, because such languages can manipulate unbounded
>> (potentially infinite) sequences of values. Such sequences can be handled
>> in Ada, too, but with more effort -- they are not "built in" to Ada.
>
> Infinite division does not require big numbers, which Ada 22 has, but I
> wound not use them anyway because the performance would be abysmal.
>
> BTW, Ada is perfect for numeric algorithms no need to resort to functional
> mess... (:-))

Perfect? That's a bold claim!

Mind you, I don't think this problem is really a numerical one in that
sense. It needs some simple integer arithmetic but then every language
is perfect for that sort of arithmetic.

Using a functional mess (Haskell) a simple, native solution (i.e. using
no modules) is only 9 lines long.

I don't want to start a language war. Ada is just more 'wordy' by
deliberate design so a simple Ada solution is inevitably going to be
longer in terms of lines. Rather my purpose in posting is to steer the
OP away from thinking of this as a numerical problem in the classical
sense. It really isn't.

--
Ben.

Re: project euler 26

<ud5amn$1jkrc$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9993&group=comp.lang.ada#9993

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 4 Sep 2023 21:20:56 +0200
Organization: A noiseless patient Spider
Lines: 53
Message-ID: <ud5amn$1jkrc$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 4 Sep 2023 19:20:55 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="84abbd2dc2e4fea6082302e85e06124d";
logging-data="1692524"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/K1iz29hRQLbxtrwGPDdlVcCr+PqnEj2c="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:G0MMDzEv/POWxittBTn5CDzcxlA=
Content-Language: en-US
In-Reply-To: <878r9mudvj.fsf@bsb.me.uk>
 by: Dmitry A. Kazakov - Mon, 4 Sep 2023 19:20 UTC

On 2023-09-04 18:01, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-04 13:06, Niklas Holsti wrote:
>>> On 2023-09-04 12:19, CSYH (QAQ) wrote:
>>>> I am new to Ada, I know is there a good way to start this program?
>>>> thanks
>>>> https://projecteuler.net/problem=26
>>> First invent/discover the method (algorithm) for solving the problem,
>>> without thinking about the programming language.
>>> I don't think any language has built-in features that would lead to a
>>> direct solution, although some functional language with lazy evaluation
>>> could come close, because such languages can manipulate unbounded
>>> (potentially infinite) sequences of values. Such sequences can be handled
>>> in Ada, too, but with more effort -- they are not "built in" to Ada.
>>
>> Infinite division does not require big numbers, which Ada 22 has, but I
>> wound not use them anyway because the performance would be abysmal.
>>
>> BTW, Ada is perfect for numeric algorithms no need to resort to functional
>> mess... (:-))
>
> Perfect? That's a bold claim!

Ada is a very improved descendant of Algol 60, which was designed to
codify algorithms.

> Mind you, I don't think this problem is really a numerical one in that
> sense. It needs some simple integer arithmetic but then every language
> is perfect for that sort of arithmetic.

That is still all about algorithms (rather than about for example
building abstractions as in the case of OOP)

> Using a functional mess (Haskell) a simple, native solution (i.e. using
> no modules) is only 9 lines long.

Apart from the fundamental inconsistency of functional paradigm:
computing is about transition of states and nothing else; the imperative
languages express solutions, i.e. an algorithm. Functional, and in
general, declarative languages express puzzles.

They remind me a math examination tasks on studying a function. Here is
a definition. Go figure out the properties and behavior...

Or, if you want, functional is like a chess composition: white to move
and checkmate in 4 moves. Challenging, but Ada is about playing chess.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<87a5u1u1yv.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9994&group=comp.lang.ada#9994

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 04 Sep 2023 21:18:16 +0100
Organization: A noiseless patient Spider
Lines: 60
Message-ID: <87a5u1u1yv.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="e2cb716c5442438ebe9264e332ee95d9";
logging-data="1710501"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/Q1rY4WPB1sY6dAm5QKp6lIi6tlBJhRgU="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:o1j/PPPMaWpJUZd2IjGdYBybSQs=
sha1:GxMOXMrMWSDiQkr9d1fFyakBvjo=
X-BSB-Auth: 1.8ca3d4d0d434a95267f5.20230904211816BST.87a5u1u1yv.fsf@bsb.me.uk
 by: Ben Bacarisse - Mon, 4 Sep 2023 20:18 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-04 18:01, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2023-09-04 13:06, Niklas Holsti wrote:
>>>> On 2023-09-04 12:19, CSYH (QAQ) wrote:
>>>>> I am new to Ada, I know is there a good way to start this program?
>>>>> thanks
>>>>> https://projecteuler.net/problem=26
>>>> First invent/discover the method (algorithm) for solving the problem,
>>>> without thinking about the programming language.
>>>> I don't think any language has built-in features that would lead to a
>>>> direct solution, although some functional language with lazy evaluation
>>>> could come close, because such languages can manipulate unbounded
>>>> (potentially infinite) sequences of values. Such sequences can be handled
>>>> in Ada, too, but with more effort -- they are not "built in" to Ada.
>>>
>>> Infinite division does not require big numbers, which Ada 22 has, but I
>>> wound not use them anyway because the performance would be abysmal.
>>>
>>> BTW, Ada is perfect for numeric algorithms no need to resort to functional
>>> mess... (:-))
>> Perfect? That's a bold claim!
>
> Ada is a very improved descendant of Algol 60, which was designed to codify
> algorithms.

Yes, though I was respond to you narrower remark about being perfect for
numeric algorithms. Are you expending that to perfect for every kind of
algorithm?

>> Mind you, I don't think this problem is really a numerical one in that
>> sense. It needs some simple integer arithmetic but then every language
>> is perfect for that sort of arithmetic.
>
> That is still all about algorithms

Yes but, again, that's not what I was responding to.

> (rather than about for example building
> abstractions as in the case of OOP)

That's interesting. You don't consider using functions and procedures
(possibly higher-order ones) to be a way to build abstractions?

>> Using a functional mess (Haskell) a simple, native solution (i.e. using
>> no modules) is only 9 lines long.
>
> Apart from the fundamental inconsistency of functional paradigm: computing
> is about transition of states and nothing else; the imperative languages
> express solutions, i.e. an algorithm. Functional, and in general,
> declarative languages express puzzles.

Rather than try to unpick that paragraph I'll just say that they can,
none the less, give simple solutions to this sort of programming
problem.

--
Ben.

Re: project euler 26

<ud5gh7$1kigc$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9995&group=comp.lang.ada#9995

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Mon, 4 Sep 2023 23:00:25 +0200
Organization: A noiseless patient Spider
Lines: 40
Message-ID: <ud5gh7$1kigc$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Mon, 4 Sep 2023 21:00:23 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="84abbd2dc2e4fea6082302e85e06124d";
logging-data="1722892"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+MmBg/NKio9natClNKqS5hFfj4PywCWAs="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:XKtFpt+IFWpw2Pesalk7jQeq4kE=
Content-Language: en-US
In-Reply-To: <87a5u1u1yv.fsf@bsb.me.uk>
 by: Dmitry A. Kazakov - Mon, 4 Sep 2023 21:00 UTC

On 2023-09-04 22:18, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-04 18:01, Ben Bacarisse wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> BTW, Ada is perfect for numeric algorithms no need to resort to functional
>>>> mess... (:-))
>>> Perfect? That's a bold claim!
>>
>> Ada is a very improved descendant of Algol 60, which was designed to codify
>> algorithms.
>
> Yes, though I was respond to you narrower remark about being perfect for
> numeric algorithms.

Yes, Ada is.

> Are you expending that to perfect for every kind of
> algorithm?

Algorithms are defined in terms of established types, e.g. model numbers
or other well known structures. Ada works pretty good for non-numeric
algorithms too. So well, that many Ada programmers never go beyond this
stage and proclaim anathema to anything above it.

>> (rather than about for example building
>> abstractions as in the case of OOP)
>
> That's interesting. You don't consider using functions and procedures
> (possibly higher-order ones) to be a way to build abstractions?

No, they do not introduce new types and do not form some structure of
their values. And "using" is not an abstraction anyway.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<8734ztttpc.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9996&group=comp.lang.ada#9996

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Tue, 05 Sep 2023 00:16:47 +0100
Organization: A noiseless patient Spider
Lines: 91
Message-ID: <8734ztttpc.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="2907f66c348ba0da34ad87ef57ce8447";
logging-data="1759040"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+RQDBfB92OUYAWvCH9APAt4VTlzdNUmzg="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:4ESW1qH9MX/UZuzufgw9V/N6uUU=
sha1:3DgbzGENaZ4xRVS6xJ33vwO9GH0=
X-BSB-Auth: 1.767e128e93d1655732ff.20230905001647BST.8734ztttpc.fsf@bsb.me.uk
 by: Ben Bacarisse - Mon, 4 Sep 2023 23:16 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-04 22:18, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2023-09-04 18:01, Ben Bacarisse wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>>
>>>>> BTW, Ada is perfect for numeric algorithms no need to resort to functional
>>>>> mess... (:-))
>>>> Perfect? That's a bold claim!
>>>
>>> Ada is a very improved descendant of Algol 60, which was designed to codify
>>> algorithms.
>> Yes, though I was respond to you narrower remark about being perfect for
>> numeric algorithms.
>
> Yes, Ada is.

:-)

>>> (rather than about for example building
>>> abstractions as in the case of OOP)
>>
>> That's interesting. You don't consider using functions and procedures
>> (possibly higher-order ones) to be a way to build abstractions?
>
> No, they do not introduce new types and do not form some structure of their
> values. And "using" is not an abstraction anyway.

The term "abstraction" is usually taken to be more general than that so
as to include function (or procedural) abstraction.

Ada is good at that, but the syntax is sufficiently cumbersome that I
think it discourages people from exploiting that part of the language.
Mind you, I am no Ada expert so maybe it's simpler to do than I think.

Here's my Ada solution:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Ordered_Maps; use Ada.Containers;

procedure Euler_26 is

function Period(Divisor: Positive) return Positive is
Index: Natural := 0;
Carry: Natural := 1;

package Carry_Maps is new Ordered_Maps(Natural, Natural);
use Carry_Maps;
Carries: Map;
Loc: Cursor;
begin
loop
Loc := Carries.Find(Carry);
exit when Loc /= No_Element;
Carries.Insert(Carry, Index);
Index := Index + 1;
Carry := Carry mod Divisor * 10;
end loop;
return Index - Element(Loc);
end Period;

Max_Period: Natural := 1;
Divisor_With_Max_Period: Natural := 1;
begin
for D in 2..999 loop
declare Ds_Period: constant Positive := Period(D);
begin
if Ds_Period > Max_Period
then
Divisor_With_Max_Period := D;
Max_Period := Ds_Period;
end if;
end;
end loop;
Put_Line(Integer'Image(Divisor_With_Max_Period));
end Euler_26;

The part that finds the D that maximises Period(D) is just boilerplate
code. I know this can be abstracted out in Ada, but I think the syntax
is messy. I was hoping to find (or be able to write) a generic function
that takes an 'iterable' (if that's the right word) and a function, and
which returns the element that maximises the function. I got stuck
trying. Maybe someone can help?

I know it won't make this program shorter, but it would be interesting
to know how it might be done.

--
Ben.

Re: project euler 26

<ud6l23$1sq44$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9997&group=comp.lang.ada#9997

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Tue, 5 Sep 2023 09:23:46 +0200
Organization: A noiseless patient Spider
Lines: 37
Message-ID: <ud6l23$1sq44$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 5 Sep 2023 07:23:47 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="7b327c4b880c05c3511b9a0af588fe44";
logging-data="1992836"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Kzwn9gEujIgEMCFK/2jD/LEYU+0cPGAo="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:p3/s/UENhT/RR25uQLV9mYHl26Q=
Content-Language: en-US
In-Reply-To: <8734ztttpc.fsf@bsb.me.uk>
 by: Dmitry A. Kazakov - Tue, 5 Sep 2023 07:23 UTC

On 2023-09-05 01:16, Ben Bacarisse wrote:

> The term "abstraction" is usually taken to be more general than that so
> as to include function (or procedural) abstraction.

These are means of software decomposition rather than abstraction (of
something).

> Ada is good at that, but the syntax is sufficiently cumbersome that I
> think it discourages people from exploiting that part of the language.
> Mind you, I am no Ada expert so maybe it's simpler to do than I think.

If the program does not resemble electric transmission noise, some
people call the language syntax cumbersome... (:-))

> Here's my Ada solution:
>
> with Ada.Text_IO; use Ada.Text_IO;
> with Ada.Containers.Ordered_Maps; use Ada.Containers;
>
> procedure Euler_26 is
>
> function Period(Divisor: Positive) return Positive is

You cannot use a number here because the period may have leading zeros.

> I know it won't make this program shorter, but it would be interesting
> to know how it might be done.

The goal of engineering is not making programs shorter, it is to make
them understandable, safer, reusable, maintainable, extensible, integrable.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<87fs3ssl6v.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9998&group=comp.lang.ada#9998

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Tue, 05 Sep 2023 16:18:16 +0100
Organization: A noiseless patient Spider
Lines: 63
Message-ID: <87fs3ssl6v.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="2907f66c348ba0da34ad87ef57ce8447";
logging-data="2141871"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+kdRKWyBnwUi5kXH4dYdMn8NxLmPu4Y+s="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:WAajG6VDWcbL58WZKcDawLyKaeE=
sha1:L3npjcCMANz3SkioAvwoCz5M+Ms=
X-BSB-Auth: 1.89015ecd8a8ec650a205.20230905161816BST.87fs3ssl6v.fsf@bsb.me.uk
 by: Ben Bacarisse - Tue, 5 Sep 2023 15:18 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-05 01:16, Ben Bacarisse wrote:
>
>> The term "abstraction" is usually taken to be more general than that so
>> as to include function (or procedural) abstraction.
>
> These are means of software decomposition rather than abstraction (of
> something).

That's not how the word is usually used. Obviously I can't (and don't
want to) change your mind, but algorithms can be abstracted as well as
data.

I was hoping someone could how me how in for the example program I gave
since that's an area of Ada I am not familiar with (but I's sure it's
possible).

>> Ada is good at that, but the syntax is sufficiently cumbersome that I
>> think it discourages people from exploiting that part of the language.
>> Mind you, I am no Ada expert so maybe it's simpler to do than I think.
>
> If the program does not resemble electric transmission noise, some people
> call the language syntax cumbersome... (:-))

That's true. But there are also constructs that are genuinely
cumbersome in some languages. Anyway, to find out more, I was hoping
someone would show me what it looks like in Ada -- I outlined what I
wanted to do after the code I posted.

>> Here's my Ada solution:
>> with Ada.Text_IO; use Ada.Text_IO;
>> with Ada.Containers.Ordered_Maps; use Ada.Containers;
>> procedure Euler_26 is
>> function Period(Divisor: Positive) return Positive is
>
> You cannot use a number here because the period may have leading
> zeros.

The function returns the decimal period of 1/Divisor. I don't believe
there is a bug, but if you think you've found one, I'd like to know
about it.

Of course there can be leading zeros, but my algorithm ignores the
digits and determines the period using the "carry" instead.

>> I know it won't make this program shorter, but it would be interesting
>> to know how it might be done.
>
> The goal of engineering is not making programs shorter, it is to make them
> understandable, safer, reusable, maintainable, extensible, integrable.

Yes. That's exactly why I was asking for someone who knows Ada better
to show me how to write the reusable component I described. There was
boiler plate code in my program that could be abstracted out into a
generic function (or package?) so that any function can be maximised
over some range or, better yet, any iterable type (if that's how Ada
does things).

Can someone here show me how?

--
Ben.

Re: project euler 26

<ud7nba$22ejn$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=9999&group=comp.lang.ada#9999

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Tue, 5 Sep 2023 19:08:59 +0200
Organization: A noiseless patient Spider
Lines: 131
Message-ID: <ud7nba$22ejn$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Tue, 5 Sep 2023 17:08:58 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="7b327c4b880c05c3511b9a0af588fe44";
logging-data="2177655"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/VpnF3iDumhZngobYBrrjzDdCsedXMV7o="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:eXe1Vab3WptMusDNVqoypT2BZ7g=
Content-Language: en-US
In-Reply-To: <87fs3ssl6v.fsf@bsb.me.uk>
 by: Dmitry A. Kazakov - Tue, 5 Sep 2023 17:08 UTC

On 2023-09-05 17:18, Ben Bacarisse wrote:

> There was
> boiler plate code in my program that could be abstracted out into a
> generic function (or package?) so that any function can be maximised
> over some range or, better yet, any iterable type (if that's how Ada
> does things).

> Can someone here show me how?

You define some classes. Either generic or tagged. E.g. a generic class
of functions that uses two generic classes of the argument and the value:

generic
-- Ordered argument
type Argument_Type is private;
with function Next (Value : Argument_Type)
return Argument_Type is <>;
with function "<" (Left, Right : Argument_Type)
return Boolean is <>;
with function "=" (Left, Right : Argument_Type)
return Boolean is <>;
-- Comparable value
type Value_Type is private;
with function "<" (Left, Right : Value_Type ) return Boolean is <>;
-- Function type
with function Func (Argument : Argument_Type) return Value_Type;
function Generic_Maximum_At (Left, Right : Argument_Type)
return Value_Type;

and the implementation

function Generic_Maximum_At (Left, Right : Argument_Type)
return Value_Type is
Argument : Argument_Type := Left;
Max : Value_Type;
Value : Value_Type;
begin
if Right < Left then
raise Constraint_Error with "Empty interval";
end if;
Max := Func (Argument);
while not (Argument = Right) loop
Argument := Next (Argument);
Value := Func (Argument);
if Max < Value then
Max := Value;
end if;
end loop;
return Max;
end Generic_Maximum_At;

or you can choose to pass the function as an argument:

generic
-- Ordered argument
type Argument_Type is private;
with function Next (Value : Argument_Type)
return Argument_Type is <>;
with function "<" (Left, Right : Argument_Type)
return Boolean is <>;
-- Comparable value
type Value_Type is private;
with function "<" (Left, Right : Value_Type) return Boolean is <>;
function Generic_Maximum_At
( Left, Right : Argument_Type;
Func : access function (Argument : Argument_Type)
return Value_Type
) return Value_Type;

Or you can make it a package which is usually a better choice as one can
pack into it several entities sharing the same generic interface:

generic
-- Ordered argument
type Argument_Type is private;
with function Next (Value : Argument_Type)
return Argument_Type is <>;
with function "<" (Left, Right : Argument_Type )
return Boolean is <>;
with function "=" (Left, Right : Argument_Type)
return Boolean is <>;
-- Comparable value
type Value_Type is private;
with function "<" (Left, Right : Value_Type) return Boolean is <>;
package Generic_Discrete_Comparable_Valued is
function Maximum_At
( Left, Right : Argument_Type;
Func : access function (Argument : Argument_Type)
return Value_Type
) return Value_Type;
-- Other useless functions
end Generic_Discrete_Comparable_Valued;

The generic classes of arguments/values can be in turn factored out into
reusable generic packages:

generic
-- Ordered argument
type Argument_Type is private;
with function Next (Value : Argument_Type) return Argument_Type is <>;
with function "<" (Left, Right : Argument_Type) return Boolean is <>;
with function "=" (Left, Right : Argument_Type) return Boolean is <>;
package Generic_Arguments is
end Generic_Arguments;

generic
-- Comparable value
type Value_Type is private;
with function "<" (Left, Right : Value_Type ) return Boolean is <>;
package Generic_Values is
end Generic_Values;

generic
with package Arguments is new Generic_Arguments (<>);
with package Values is new Generic_Values (<>);
package Generic_Discrete_Comparable_Valued is
use Arguments, Values;
function Maximum_At
( Left, Right : Argument_Type;
Func : access function (Argument : Argument_Type)
return Value_Type
) return Value_Type;
-- Other useless functions
end Generic_Discrete_Comparable_Valued;

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<klp76gFjuvbU1@mid.individual.net>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10000&group=comp.lang.ada#10000

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail
From: findlaybill@blueyonder.co.uk (moi)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Tue, 5 Sep 2023 18:35:10 +0100
Lines: 46
Message-ID: <klp76gFjuvbU1@mid.individual.net>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
Mime-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Trace: individual.net PdsdQ5qTwY0Jd2/GTkGlYQrJ9ZZT90ditJyoKwNDv3H1OYwzh7
Cancel-Lock: sha1:35KoZUmyuebYAus6/ilDLTkhpCk= sha256:+sTsU/RUO+FoZxrEaP6+bqWxQbGqyGABLviiC4lhakM=
User-Agent: Mozilla Thunderbird
Content-Language: en-GB
In-Reply-To: <ud6l23$1sq44$1@dont-email.me>
 by: moi - Tue, 5 Sep 2023 17:35 UTC

On 05/09/2023 08:23, Dmitry A. Kazakov wrote:
> On 2023-09-05 01:16, Ben Bacarisse wrote:
>
>> The term "abstraction" is usually taken to be more general than that so
>> as to include function (or procedural) abstraction.
>
> These are means of software decomposition rather than abstraction (of
> something).

They are both of these things, actually.

>
>> Ada is good at that, but the syntax is sufficiently cumbersome that I
>> think it discourages people from exploiting that part of the language.
>> Mind you, I am no Ada expert so maybe it's simpler to do than I think.
>
> If the program does not resemble electric transmission noise, some
> people call the language syntax cumbersome... (:-))

8-)

>> Here's my Ada solution:
>>
>> with Ada.Text_IO; use Ada.Text_IO;
>> with Ada.Containers.Ordered_Maps; use Ada.Containers;
>>
>> procedure Euler_26 is
>>
>>     function Period(Divisor: Positive) return Positive is
>
> You cannot use a number here because the period may have leading zeros.
>
>> I know it won't make this program shorter, but it would be interesting
>> to know how it might be done.
>
> The goal of engineering is not making programs shorter, it is to make
> them understandable, safer, reusable, maintainable, extensible, integrable.

Hear, hear!

Functionalists do seem to have an obsession with brevity at all costs.
It's very strange.

--
Bill F.

Re: project euler 26

<87a5u0rts0.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10001&group=comp.lang.ada#10001

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Wed, 06 Sep 2023 02:10:23 +0100
Organization: A noiseless patient Spider
Lines: 135
Message-ID: <87a5u0rts0.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="28c87aba986c3fbe6225b4a2a066932e";
logging-data="2312327"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+AbwzVclP68jBd4Z/+un/VveGZw7Lv02k="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:UdmQdwiavArjukueY/hzb7WwWgw=
sha1:cs0F/5BDWr6UlfTbt2WcA9C9AOM=
X-BSB-Auth: 1.c8c19c3e65c6f903ca99.20230906021023BST.87a5u0rts0.fsf@bsb.me.uk
 by: Ben Bacarisse - Wed, 6 Sep 2023 01:10 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-05 17:18, Ben Bacarisse wrote:
>
>> There was
>> boiler plate code in my program that could be abstracted out into a
>> generic function (or package?) so that any function can be maximised
>> over some range or, better yet, any iterable type (if that's how Ada
>> does things).
>
>> Can someone here show me how?
>
> You define some classes. Either generic or tagged. E.g. a generic class of
> functions that uses two generic classes of the argument and the value:
>
> generic
> -- Ordered argument
> type Argument_Type is private;
> with function Next (Value : Argument_Type)
> return Argument_Type is <>;
> with function "<" (Left, Right : Argument_Type)
> return Boolean is <>;
> with function "=" (Left, Right : Argument_Type)
> return Boolean is <>;
> -- Comparable value
> type Value_Type is private;
> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
> -- Function type
> with function Func (Argument : Argument_Type) return Value_Type;
> function Generic_Maximum_At (Left, Right : Argument_Type)
> return Value_Type;
>
> and the implementation
>
> function Generic_Maximum_At (Left, Right : Argument_Type)
> return Value_Type is
> Argument : Argument_Type := Left;
> Max : Value_Type;
> Value : Value_Type;
> begin
> if Right < Left then
> raise Constraint_Error with "Empty interval";
> end if;
> Max := Func (Argument);
> while not (Argument = Right) loop
> Argument := Next (Argument);
> Value := Func (Argument);
> if Max < Value then
> Max := Value;
> end if;
> end loop;
> return Max;
> end Generic_Maximum_At;
>
> or you can choose to pass the function as an argument:
>
> generic
> -- Ordered argument
> type Argument_Type is private;
> with function Next (Value : Argument_Type)
> return Argument_Type is <>;
> with function "<" (Left, Right : Argument_Type)
> return Boolean is <>;
> -- Comparable value
> type Value_Type is private;
> with function "<" (Left, Right : Value_Type) return Boolean is <>;
> function Generic_Maximum_At
> ( Left, Right : Argument_Type;
> Func : access function (Argument : Argument_Type)
> return Value_Type
> ) return Value_Type;
>
> Or you can make it a package which is usually a better choice as one can
> pack into it several entities sharing the same generic interface:
>
> generic
> -- Ordered argument
> type Argument_Type is private;
> with function Next (Value : Argument_Type)
> return Argument_Type is <>;
> with function "<" (Left, Right : Argument_Type )
> return Boolean is <>;
> with function "=" (Left, Right : Argument_Type)
> return Boolean is <>;
> -- Comparable value
> type Value_Type is private;
> with function "<" (Left, Right : Value_Type) return Boolean is <>;
> package Generic_Discrete_Comparable_Valued is
> function Maximum_At
> ( Left, Right : Argument_Type;
> Func : access function (Argument : Argument_Type)
> return Value_Type
> ) return Value_Type;
> -- Other useless functions
> end Generic_Discrete_Comparable_Valued;
>
> The generic classes of arguments/values can be in turn factored out into
> reusable generic packages:
>
> generic
> -- Ordered argument
> type Argument_Type is private;
> with function Next (Value : Argument_Type) return Argument_Type is <>;
> with function "<" (Left, Right : Argument_Type) return Boolean is <>;
> with function "=" (Left, Right : Argument_Type) return Boolean is <>;
> package Generic_Arguments is
> end Generic_Arguments;
>
> generic
> -- Comparable value
> type Value_Type is private;
> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
> package Generic_Values is
> end Generic_Values;
>
> generic
> with package Arguments is new Generic_Arguments (<>);
> with package Values is new Generic_Values (<>);
> package Generic_Discrete_Comparable_Valued is
> use Arguments, Values;
> function Maximum_At
> ( Left, Right : Argument_Type;
> Func : access function (Argument : Argument_Type)
> return Value_Type
> ) return Value_Type;
> -- Other useless functions
> end Generic_Discrete_Comparable_Valued;

Thank you. I can't yet see how to use any of these alternatives, but
that's my problem. Are there any good online sources on Ada generic
programming so I can find out how to implement and use this short of
package?

--
Ben.

Re: project euler 26

<ud98do$2dbqr$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10002&group=comp.lang.ada#10002

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Wed, 6 Sep 2023 09:06:31 +0200
Organization: A noiseless patient Spider
Lines: 184
Message-ID: <ud98do$2dbqr$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 6 Sep 2023 07:06:32 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="45219ce80d83fc0bae96dda1999b3d4d";
logging-data="2535259"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19gT7ERQs6i+HK1yqDKuydx+SOHM4oW3xs="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:RZuYPKufC585eEEXZfUcerqeWvY=
In-Reply-To: <87a5u0rts0.fsf@bsb.me.uk>
Content-Language: en-US
 by: Dmitry A. Kazakov - Wed, 6 Sep 2023 07:06 UTC

On 2023-09-06 03:10, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-05 17:18, Ben Bacarisse wrote:
>>
>>> There was
>>> boiler plate code in my program that could be abstracted out into a
>>> generic function (or package?) so that any function can be maximised
>>> over some range or, better yet, any iterable type (if that's how Ada
>>> does things).
>>
>>> Can someone here show me how?
>>
>> You define some classes. Either generic or tagged. E.g. a generic class of
>> functions that uses two generic classes of the argument and the value:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>> -- Function type
>> with function Func (Argument : Argument_Type) return Value_Type;
>> function Generic_Maximum_At (Left, Right : Argument_Type)
>> return Value_Type;
>>
>> and the implementation
>>
>> function Generic_Maximum_At (Left, Right : Argument_Type)
>> return Value_Type is
>> Argument : Argument_Type := Left;
>> Max : Value_Type;
>> Value : Value_Type;
>> begin
>> if Right < Left then
>> raise Constraint_Error with "Empty interval";
>> end if;
>> Max := Func (Argument);
>> while not (Argument = Right) loop
>> Argument := Next (Argument);
>> Value := Func (Argument);
>> if Max < Value then
>> Max := Value;
>> end if;
>> end loop;
>> return Max;
>> end Generic_Maximum_At;
>>
>> or you can choose to pass the function as an argument:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>> function Generic_Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>>
>> Or you can make it a package which is usually a better choice as one can
>> pack into it several entities sharing the same generic interface:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type)
>> return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type )
>> return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type)
>> return Boolean is <>;
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>> package Generic_Discrete_Comparable_Valued is
>> function Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>> -- Other useless functions
>> end Generic_Discrete_Comparable_Valued;
>>
>> The generic classes of arguments/values can be in turn factored out into
>> reusable generic packages:
>>
>> generic
>> -- Ordered argument
>> type Argument_Type is private;
>> with function Next (Value : Argument_Type) return Argument_Type is <>;
>> with function "<" (Left, Right : Argument_Type) return Boolean is <>;
>> with function "=" (Left, Right : Argument_Type) return Boolean is <>;
>> package Generic_Arguments is
>> end Generic_Arguments;
>>
>> generic
>> -- Comparable value
>> type Value_Type is private;
>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>> package Generic_Values is
>> end Generic_Values;
>>
>> generic
>> with package Arguments is new Generic_Arguments (<>);
>> with package Values is new Generic_Values (<>);
>> package Generic_Discrete_Comparable_Valued is
>> use Arguments, Values;
>> function Maximum_At
>> ( Left, Right : Argument_Type;
>> Func : access function (Argument : Argument_Type)
>> return Value_Type
>> ) return Value_Type;
>> -- Other useless functions
>> end Generic_Discrete_Comparable_Valued;
>
> Thank you. I can't yet see how to use any of these alternatives, but
> that's my problem.

It is pretty much straightforward. E.g. the last one:

package Arguments is new Generic_Arguments (Integer, Integer'Succ);
package Values is new Generic_Values (Integer);
package Functions is
new Generic_Discrete_Comparable_Valued (Arguments, Values);

Now you can print the maximum of your Period function:

Put_Line
( "Max at"
& Integer'Image (Functions.Maximum_At (2, 999, Period'Access))
);

> Are there any good online sources on Ada generic
> programming so I can find out how to implement and use this short of
> package?

Actually I provided an implementation above. Here it is again:

package body Generic_Discrete_Comparable_Valued is
function Maximum_At
( Left, Right : Argument_Type;
Func : access function (Argument : Argument_Type)
return Value_Type
) return Value_Type is
Argument : Argument_Type := Left;
Max : Value_Type;
Value : Value_Type;
begin
if Right < Left then
raise Constraint_Error with "Empty interval";
end if;
Max := Func (Argument);
while not (Argument = Right) loop
Argument := Next (Argument);
Value := Func (Argument);
if Max < Value then
Max := Value;
end if;
end loop;
return Max;
end Maximum_At;
end Generic_Discrete_Comparable_Valued;

(The packages Generic_Arguments and Generic_Values have no bodies)

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<87jzt3qqlb.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10005&group=comp.lang.ada#10005

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Wed, 06 Sep 2023 16:16:48 +0100
Organization: A noiseless patient Spider
Lines: 199
Message-ID: <87jzt3qqlb.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="28c87aba986c3fbe6225b4a2a066932e";
logging-data="2689279"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/0dTA9M9y8eFdgGfVCLsWn4+6QyXcSOQA="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:uPIsd93ySQsVhuK+8cW+B2pU91g=
sha1:1zkAA6qj96qXmRxThuyxyq7xc60=
X-BSB-Auth: 1.0c33ef045499c757a80c.20230906161648BST.87jzt3qqlb.fsf@bsb.me.uk
 by: Ben Bacarisse - Wed, 6 Sep 2023 15:16 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-06 03:10, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2023-09-05 17:18, Ben Bacarisse wrote:
>>>
>>>> There was
>>>> boiler plate code in my program that could be abstracted out into a
>>>> generic function (or package?) so that any function can be maximised
>>>> over some range or, better yet, any iterable type (if that's how Ada
>>>> does things).
>>>
>>>> Can someone here show me how?
>>>
>>> You define some classes. Either generic or tagged. E.g. a generic class of
>>> functions that uses two generic classes of the argument and the value:
>>>
>>> generic
>>> -- Ordered argument
>>> type Argument_Type is private;
>>> with function Next (Value : Argument_Type)
>>> return Argument_Type is <>;
>>> with function "<" (Left, Right : Argument_Type)
>>> return Boolean is <>;
>>> with function "=" (Left, Right : Argument_Type)
>>> return Boolean is <>;
>>> -- Comparable value
>>> type Value_Type is private;
>>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>>> -- Function type
>>> with function Func (Argument : Argument_Type) return Value_Type;
>>> function Generic_Maximum_At (Left, Right : Argument_Type)
>>> return Value_Type;
>>>
>>> and the implementation
>>>
>>> function Generic_Maximum_At (Left, Right : Argument_Type)
>>> return Value_Type is
>>> Argument : Argument_Type := Left;
>>> Max : Value_Type;
>>> Value : Value_Type;
>>> begin
>>> if Right < Left then
>>> raise Constraint_Error with "Empty interval";
>>> end if;
>>> Max := Func (Argument);
>>> while not (Argument = Right) loop
>>> Argument := Next (Argument);
>>> Value := Func (Argument);
>>> if Max < Value then
>>> Max := Value;
>>> end if;
>>> end loop;
>>> return Max;
>>> end Generic_Maximum_At;
>>>
>>> or you can choose to pass the function as an argument:
>>>
>>> generic
>>> -- Ordered argument
>>> type Argument_Type is private;
>>> with function Next (Value : Argument_Type)
>>> return Argument_Type is <>;
>>> with function "<" (Left, Right : Argument_Type)
>>> return Boolean is <>;
>>> -- Comparable value
>>> type Value_Type is private;
>>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>>> function Generic_Maximum_At
>>> ( Left, Right : Argument_Type;
>>> Func : access function (Argument : Argument_Type)
>>> return Value_Type
>>> ) return Value_Type;
>>>
>>> Or you can make it a package which is usually a better choice as one can
>>> pack into it several entities sharing the same generic interface:
>>>
>>> generic
>>> -- Ordered argument
>>> type Argument_Type is private;
>>> with function Next (Value : Argument_Type)
>>> return Argument_Type is <>;
>>> with function "<" (Left, Right : Argument_Type )
>>> return Boolean is <>;
>>> with function "=" (Left, Right : Argument_Type)
>>> return Boolean is <>;
>>> -- Comparable value
>>> type Value_Type is private;
>>> with function "<" (Left, Right : Value_Type) return Boolean is <>;
>>> package Generic_Discrete_Comparable_Valued is
>>> function Maximum_At
>>> ( Left, Right : Argument_Type;
>>> Func : access function (Argument : Argument_Type)
>>> return Value_Type
>>> ) return Value_Type;
>>> -- Other useless functions
>>> end Generic_Discrete_Comparable_Valued;
>>>
>>> The generic classes of arguments/values can be in turn factored out into
>>> reusable generic packages:
>>>
>>> generic
>>> -- Ordered argument
>>> type Argument_Type is private;
>>> with function Next (Value : Argument_Type) return Argument_Type is <>;
>>> with function "<" (Left, Right : Argument_Type) return Boolean is <>;
>>> with function "=" (Left, Right : Argument_Type) return Boolean is <>;
>>> package Generic_Arguments is
>>> end Generic_Arguments;
>>>
>>> generic
>>> -- Comparable value
>>> type Value_Type is private;
>>> with function "<" (Left, Right : Value_Type ) return Boolean is <>;
>>> package Generic_Values is
>>> end Generic_Values;
>>>
>>> generic
>>> with package Arguments is new Generic_Arguments (<>);
>>> with package Values is new Generic_Values (<>);
>>> package Generic_Discrete_Comparable_Valued is
>>> use Arguments, Values;
>>> function Maximum_At
>>> ( Left, Right : Argument_Type;
>>> Func : access function (Argument : Argument_Type)
>>> return Value_Type
>>> ) return Value_Type;
>>> -- Other useless functions
>>> end Generic_Discrete_Comparable_Valued;
>> Thank you. I can't yet see how to use any of these alternatives, but
>> that's my problem.
>
> It is pretty much straightforward. E.g. the last one:

Sure, but I am new to Ada. Well actually I first wrote Ada in the early
80s, but the project didn't go with Ada (too new I suspect) so reading
one book was the extent of my learning.

> package Arguments is new Generic_Arguments (Integer, Integer'Succ);
> package Values is new Generic_Values (Integer);

I'd probably choose more generic names for the packages since these are
more general than the names suggest. I might go with Generic_Enumerated
(since it has 'Next') and Generic_Ordered.

Just to test I knew what was going on, I changed 'while not (Argument =
Right)' to 'while Argument < Right' so as to remove the need for having
an "=" function. I doubt there are any types with "<" but not "=" but I
wanted to confirm I understood the code.

> package Functions is
> new Generic_Discrete_Comparable_Valued (Arguments, Values);
>
>
> Now you can print the maximum of your Period function:
>
> Put_Line
> ( "Max at"
> & Integer'Image (Functions.Maximum_At (2, 999, Period'Access))
> );

Thanks.

(A minor issue: to meet the specification we either need 1000 here or
the loop needs to be changed to include the upper bound (like the for
loop did in the original). Whilst it's easy to pass "one past the top
index" for Integer and so on, if the code can be made more generic it
would have to use all the values in the range because Ada has not done
the C++ hack of having XXX.end() be an iterator "one past" the actual
end of a range.)

I am curious to know how reusable this is. Can the packages be
instantiated in such a way that the argument ranges over the elements
of, say, and Ordered_Map? In some languages (C++!) one could pass a
pair of iterators here (cursors, I think in Ada-speak). I tried to do
that but I don't think Ada's cursors are ordered by < though they do
have a Next function. And if that method does work (it's quite likely
it was only my ignorance of the language that stopped it working) would
it work for built-in arrays which don't seem to have cursors.

Maybe a more generic a solution would involve passing something that can
be iterated over, rather than two values of an "enumerated" type? I
mean enumerated in the mathematical sense -- it may be the wrong word in
Ada.

I am asking you but I am also the group. I appreciate your help,
but don't want you to feel any obligation to keep helping!

>> Are there any good online sources on Ada generic
>> programming so I can find out how to implement and use this short of
>> package?
>
> Actually I provided an implementation above. Here it is again:


Click here to read the complete article
Re: project euler 26

<uda7c7$2ids2$2@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10007&group=comp.lang.ada#10007

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Wed, 6 Sep 2023 17:54:47 +0200
Organization: A noiseless patient Spider
Lines: 44
Message-ID: <uda7c7$2ids2$2@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 6 Sep 2023 15:54:47 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="45219ce80d83fc0bae96dda1999b3d4d";
logging-data="2701186"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19kUA6Kfvz/kG7GRHACoOzECaWnsC3R2yY="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:3gOuW/gfwh7m6Bk12OM7ow994kM=
In-Reply-To: <87jzt3qqlb.fsf@bsb.me.uk>
Content-Language: en-US
 by: Dmitry A. Kazakov - Wed, 6 Sep 2023 15:54 UTC

On 2023-09-06 17:16, Ben Bacarisse wrote:

> I am curious to know how reusable this is. Can the packages be
> instantiated in such a way that the argument ranges over the elements
> of, say, and Ordered_Map?

Sure:

with Ada.Containers.Ordered_Maps;

package Integer_Maps is
new Ada.Containers.Ordered_Maps (Integer, Integer);
use Integer_Maps;
package Cursor_Arguments is new Generic_Arguments (Cursor);
package Map_Values is new Generic_Values (Integer);
package Map_Functions is
new Generic_Discrete_Comparable_Valued
(Cursor_Arguments, Map_Values);

Then given X is a map: X : Map;

Map_Functions.Maximum_At (X.First, X.Last, Element'Access)

> Maybe a more generic a solution would involve passing something that can
> be iterated over, rather than two values of an "enumerated" type? I
> mean enumerated in the mathematical sense -- it may be the wrong word in
> Ada.

Yes, but Ada does not have built-in range types. Therefore such design
will not work out of the box with discrete types because 2..999 is not a
proper object in Ada. However, talking about abstractions, you can
create an interval type for the purpose or else use an ordered set of
integers.

> I am asking you but I am also the group. I appreciate your help,
> but don't want you to feel any obligation to keep helping!

No problem.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<87o7ieq3ne.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10009&group=comp.lang.ada#10009

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Thu, 07 Sep 2023 00:32:21 +0100
Organization: A noiseless patient Spider
Lines: 103
Message-ID: <87o7ieq3ne.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="347d35c8051c6481b9483e2b861d4761";
logging-data="2833814"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/QlMWjbPMGtBcFWWr7M1rWJ7rix8VpPeg="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:uBWjBnoyd1BWjcW2vhk2ANqquZ0=
sha1:j3LOEpPm8tSlA2DcATMKaKlEKxs=
X-BSB-Auth: 1.77e11959ac9ce18e30e8.20230907003221BST.87o7ieq3ne.fsf@bsb.me.uk
 by: Ben Bacarisse - Wed, 6 Sep 2023 23:32 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-06 17:16, Ben Bacarisse wrote:
>
>> I am curious to know how reusable this is. Can the packages be
>> instantiated in such a way that the argument ranges over the elements
>> of, say, and Ordered_Map?
>
> Sure:
>
> with Ada.Containers.Ordered_Maps;
>
> package Integer_Maps is
> new Ada.Containers.Ordered_Maps (Integer, Integer);
> use Integer_Maps;
> package Cursor_Arguments is new Generic_Arguments (Cursor);

Ah! So the arguments correspond to the "with" functions in the order
listed, and, since Cursor already has Next, there no need to specify
anything. One could (I've just tried) use => notation. You could have
written

package Arguments is new Generic_Arguments (Next => Positive'Succ,
Argument_Type => Positive);

in your first example -- swapping the order just to make the point
obvious. This tripped me up when I was playing around with a Cursors
solution.

There are a couple of details that prevent your Maximum_At function from
working properly in this case though. First, we can't have an empty
map, because X.Last can't be compared with X.First when either is
No_Element, so the test for Right < Left fails before the desired error
can be raised.

Second, if I try to use a Vector rather than an Ordered_Map, I am told
that:

test2.adb:97:05: error: instantiation error at line 12
test2.adb:97:05: error: no visible subprogram matches the specification for "<"

It would seem that vector cursors can't be compared using < (at least by
default). Maybe the installation needs more arguments.

Anyway, I am still not sure how to write a generic test for an empty
range.

> package Map_Values is new Generic_Values (Integer);
> package Map_Functions is
> new Generic_Discrete_Comparable_Valued
> (Cursor_Arguments, Map_Values);
>
> Then given X is a map: X : Map;
>
> Map_Functions.Maximum_At (X.First, X.Last, Element'Access)

It's possible I was not clear about what I was aiming for. I was hoping
to be able to find the maximum of some arbitrary function, taking the
function's arguments from any sequential collection. Either a simple
range of values, an array or vector of values, a list of values or even
an ordered map of values -- any ordered list of values.

The bottom line is the last argument should be something very general
like the Period function.

A fix (though it's not really ideal) would be to use function
composition here (inventing . as the composition operator):

Map_Functions.Maximum_At (X.First, X.Last, Period'Access . Element'Access)

but I don't think Ada has a function composition operator, does it?

Another solution would be to write Maximum_At so that it knows it has a
cursor argument, but then I don't think it would work for native arrays,
would it? And we'd loose plain ranges altogether.

>> Maybe a more generic a solution would involve passing something that can
>> be iterated over, rather than two values of an "enumerated" type? I
>> mean enumerated in the mathematical sense -- it may be the wrong word in
>> Ada.
>
> Yes, but Ada does not have built-in range types. Therefore such design will
> not work out of the box with discrete types because 2..999 is not a proper
> object in Ada. However, talking about abstractions, you can create an
> interval type for the purpose or else use an ordered set of integers.

But then (I think) the only function one could pass would be something
like Element as in you example above. Using an ordered set of integers
would not allow

Map_Functions.Maximum_At (Set.First, Set.Last, Period'Access)

would it?

>> I am asking you but I am also the group. I appreciate your help,
>> but don't want you to feel any obligation to keep helping!
>
> No problem.

You seem to be on your own as far as helping out is concerned!

--
Ben.

Re: project euler 26

<796f0dd5-cf5e-430b-a650-4ba85ba5f28bn@googlegroups.com>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10012&group=comp.lang.ada#10012

  copy link   Newsgroups: comp.lang.ada
X-Received: by 2002:a05:620a:8b89:b0:76f:1614:5772 with SMTP id qx9-20020a05620a8b8900b0076f16145772mr331740qkn.5.1694071870887;
Thu, 07 Sep 2023 00:31:10 -0700 (PDT)
X-Received: by 2002:a63:b254:0:b0:569:3231:ba24 with SMTP id
t20-20020a63b254000000b005693231ba24mr3731623pgo.10.1694071870540; Thu, 07
Sep 2023 00:31:10 -0700 (PDT)
Path: i2pn2.org!i2pn.org!usenet.blueworldhosting.com!diablo1.usenet.blueworldhosting.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!news-out.google.com!nntp.google.com!postnews.google.com!google-groups.googlegroups.com!not-for-mail
Newsgroups: comp.lang.ada
Date: Thu, 7 Sep 2023 00:31:09 -0700 (PDT)
In-Reply-To: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
Injection-Info: google-groups.googlegroups.com; posting-host=77.75.179.3; posting-account=ZswU3AoAAAA4QKiyoxEpA3Hh7ry7Cau3
NNTP-Posting-Host: 77.75.179.3
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
User-Agent: G2/1.0
MIME-Version: 1.0
Message-ID: <796f0dd5-cf5e-430b-a650-4ba85ba5f28bn@googlegroups.com>
Subject: Re: project euler 26
From: francesc.rocher@gmail.com (Francesc Rocher)
Injection-Date: Thu, 07 Sep 2023 07:31:10 +0000
Content-Type: text/plain; charset="UTF-8"
X-Received-Bytes: 1599
 by: Francesc Rocher - Thu, 7 Sep 2023 07:31 UTC

El dia dilluns, 4 de setembre de 2023 a les 11:19:53 UTC+2, CSYH (QAQ) va escriure:
> I am new to Ada, I know is there a good way to start this program?
> thanks
> https://projecteuler.net/problem=26

Hi CSHY,

Please take a look at my Euler tools repository, https://github.com/rocher/euler_tools (not the best math lib you'll find, I know).
I used this library tools to solve problem 26 here: https://github.com/rocher/alice-project_euler-rocher
Let me know what you think.

Re: project euler 26

<udc3id$2u9g8$2@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10014&group=comp.lang.ada#10014

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Thu, 7 Sep 2023 11:02:05 +0200
Organization: A noiseless patient Spider
Lines: 245
Message-ID: <udc3id$2u9g8$2@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Thu, 7 Sep 2023 09:02:05 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="3e4fde5204bf1fe9ab276fdba6340f70";
logging-data="3089928"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19G+JSG5ZU5CTeA/QI409dl05geV34nefo="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:lELjRaGNb9vWkPe0cpNcugNaqiw=
In-Reply-To: <87o7ieq3ne.fsf@bsb.me.uk>
Content-Language: en-US
 by: Dmitry A. Kazakov - Thu, 7 Sep 2023 09:02 UTC

On 2023-09-07 01:32, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>
>>> I am curious to know how reusable this is. Can the packages be
>>> instantiated in such a way that the argument ranges over the elements
>>> of, say, and Ordered_Map?
>>
>> Sure:
>>
>> with Ada.Containers.Ordered_Maps;
>>
>> package Integer_Maps is
>> new Ada.Containers.Ordered_Maps (Integer, Integer);
>> use Integer_Maps;
>> package Cursor_Arguments is new Generic_Arguments (Cursor);
>
> Ah! So the arguments correspond to the "with" functions in the order
> listed, and, since Cursor already has Next, there no need to specify
> anything.

Yes, because the formal argument is

with function Next (Value : Argument_Type)
return Argument_Type is <>;

If it were

with function Next (Value : Argument_Type)
return Argument_Type;

You would have to specify the actual. The part "is <>" tells to match a
visible function Next.

> There are a couple of details that prevent your Maximum_At function from
> working properly in this case though. First, we can't have an empty
> map, because X.Last can't be compared with X.First when either is
> No_Element, so the test for Right < Left fails before the desired error
> can be raised.

Yes, cursors is bad idea, in the end they all are pointers. No_Element
is an equivalent of null which shows.

However Maximum_At will propagate Constraint_Error if either of the
bounds is No_Element. So the implementation would work.

> Second, if I try to use a Vector rather than an Ordered_Map, I am told
> that:
>
> test2.adb:97:05: error: instantiation error at line 12
> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>
> It would seem that vector cursors can't be compared using < (at least by
> default). Maybe the installation needs more arguments.

Vector has a proper index type. All you have to do is. Given

package Integer_Vectors is
new Ada.Containers.Vectors (Integer, Integer);

Wrap Element into a function:

V : Integer_Vectors.Vector;
function Element (Index : Integer) return Integer is
begin
return V.Element (Index);
end Element;
...

and use the wrapper.

> Anyway, I am still not sure how to write a generic test for an empty
> range.

The problem is that the implementation of Cursor that breaks
abstraction. The abstraction of an argument does not permit ideal
non-values. Cursors and pointers have non-values. So if you want to test
for non-values ahead, instead of surprising the function, you need to
add a test for value validity to the abstraction:

generic
-- Ordered argument
type Argument_Type is private;
with function Valid (Value : Argument_Type) return Boolean is <>;
...
package Generic_Arguments is

Then you would pass Has_Element for it. For integers you would use
wrapped X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid
where X is an object).

> It's possible I was not clear about what I was aiming for. I was hoping
> to be able to find the maximum of some arbitrary function, taking the
> function's arguments from any sequential collection.

That is a different abstraction. You need a generic collection instead
of generic ordered values. E.g.

generic
with package Arguments is new Ada.Containers.Ordered_Sets (<>);
with package Values is new Generic_Values (<>);
package Generic_Comparable_Valued is
use Arguments, Values;
function Maximum_At
( Domain : Set;
Func : access function (Argument : Element_Type)
return Value_Type
) return Value_Type;
-- Other useless functions
end Generic_Comparable_Valued;

package body Generic_Comparable_Valued is
function Maximum_At
( Domain : Set;
Func : access function (Argument : Element_Type)
return Value_Type
) return Value_Type is
Max : Value_Type;
Value : Value_Type;
Position : Cursor;
begin
if Domain.Is_Empty then
raise Constraint_Error with "Empty set";
end if;
Position := Domain.First;
Max := Func (Element (Position));
while Position /= Domain.Last loop
Position := Next (Position);
Value := Func (Element (Position));
if Max < Value then
Max := Value;
end if;
end loop;
return Max;
end Maximum_At;
end Generic_Comparable_Valued;

> Either a simple
> range of values, an array or vector of values, a list of values or even
> an ordered map of values -- any ordered list of values.

In practice such abstraction have too much physical and mental overhead.
E.g. large sets of values implemented differently from
Ada.Containers.Ordered_Sets depending on the operations required. For
example, let you need a set complement? Usually programmers simply stick
with software patterns instead. Too much reliance of libraries make
programs incoherent.

> The bottom line is the last argument should be something very general
> like the Period function.
>
> A fix (though it's not really ideal) would be to use function
> composition here (inventing . as the composition operator):
>
> Map_Functions.Maximum_At (X.First, X.Last, Period'Access . Element'Access)
>
> but I don't think Ada has a function composition operator, does it?

No as it would require closures. So you can have a generic composition
operator, no problem, but not a first-class one. However you can simply
add Maximum_At with four arguments to the package.

> Another solution would be to write Maximum_At so that it knows it has a
> cursor argument, but then I don't think it would work for native arrays,
> would it? And we'd loose plain ranges altogether.

You can write a generic package creating array cursors:

generic
type Index_Type is (<>);
type Element_Type is private;
type Array_Type is array (Index_Type range <>) of Element_Type;
package Array_Cursors is
type Cursor is private;
function First (Container : Array_Type) return Cursor;
function Element (Position : Cursor) return Element_Type;
function "<" (Left, Right : Cursor) return Boolean;
...
private
package Dirty_Tricks is
new System.Address_To_Access_Conversions (Array_Type);
use Dirty_Tricks;
type Cursor is record
Domain : Object_Pointer;
Index : Index_Type;
end record;
end Array_Cursors;

package body Array_Cursors is
function "<" (Left, Right : Cursor) return Boolean is
begin
if Left.Domain = null or else Left.Domain /= Right.Domain then
raise Constraint_Error with "Incomparable cursors";
end if;
return Left.Index < Right.Index;
end "<";

function Element (Position : Cursor) return Element_Type is
begin
if Position.Domain = null or else
Position.Index not in Position.Domain'Range
then
raise Constraint_Error with "Invalid cursor";
else
return Position.Domain (Position.Index);
end if;
end Element;

function First (Container : Array_Type) return Cursor is
begin
if Container'Length = 0 then
raise Constraint_Error with "Empty array";
else
return (To_Pointer (Container'Address), Container'First);
end if;
end First;

end Array_Cursors;

> But then (I think) the only function one could pass would be something
> like Element as in you example above. Using an ordered set of integers
> would not allow
>
> Map_Functions.Maximum_At (Set.First, Set.Last, Period'Access)
>
> would it?

Ordered_Set cursors are ordered like Ordered_Map ones, so it should work.

>>> I am asking you but I am also the group. I appreciate your help,
>>> but don't want you to feel any obligation to keep helping!
>>
>> No problem.
>
> You seem to be on your own as far as helping out is concerned!

Because it started as a numeric puzzle. You should have asked directly
about generics or tagged types instead.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<8734zpo3fz.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10019&group=comp.lang.ada#10019

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Fri, 08 Sep 2023 02:32:00 +0100
Organization: A noiseless patient Spider
Lines: 276
Message-ID: <8734zpo3fz.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk> <udc3id$2u9g8$2@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="b39237310d6b9749d50605be679823cd";
logging-data="3353710"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+lNG/gOXpyQNl8hCFtHpS5bmPpZW6FgNc="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:VA7mSM6RR1yC0et/H0ccopaN9vE=
sha1:frIkL3EMPPkqYVarZuapZsrTgwY=
X-BSB-Auth: 1.1114e8f5b2bcbb70f427.20230908023201BST.8734zpo3fz.fsf@bsb.me.uk
 by: Ben Bacarisse - Fri, 8 Sep 2023 01:32 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-07 01:32, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>
>>>> I am curious to know how reusable this is. Can the packages be
>>>> instantiated in such a way that the argument ranges over the elements
>>>> of, say, and Ordered_Map?
>>>
>>> Sure:
>>>
>>> with Ada.Containers.Ordered_Maps;
>>>
>>> package Integer_Maps is
>>> new Ada.Containers.Ordered_Maps (Integer, Integer);
>>> use Integer_Maps;
>>> package Cursor_Arguments is new Generic_Arguments (Cursor);
>> Ah! So the arguments correspond to the "with" functions in the order
>> listed, and, since Cursor already has Next, there no need to specify
>> anything.
>
> Yes, because the formal argument is
>
> with function Next (Value : Argument_Type)
> return Argument_Type is <>;
>
> If it were
>
> with function Next (Value : Argument_Type)
> return Argument_Type;
>
> You would have to specify the actual. The part "is <>" tells to match a
> visible function Next.

Thanks. I remember that now. Given Ada's preference for words, it's a
mysterious choice.

>> There are a couple of details that prevent your Maximum_At function from
>> working properly in this case though. First, we can't have an empty
>> map, because X.Last can't be compared with X.First when either is
>> No_Element, so the test for Right < Left fails before the desired error
>> can be raised.
>
> Yes, cursors is bad idea, in the end they all are pointers. No_Element is
> an equivalent of null which shows.
>
> However Maximum_At will propagate Constraint_Error if either of the bounds
> is No_Element. So the implementation would work.

Sure, but ideally we want the error we decided on for this situation.
Since the intent is to be generic, it's a shame to get one error with
some instantiations and a different one with others.

>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>> that:
>> test2.adb:97:05: error: instantiation error at line 12
>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>> It would seem that vector cursors can't be compared using < (at least by
>> default). Maybe the installation needs more arguments.
>
> Vector has a proper index type. All you have to do is. Given
>
> package Integer_Vectors is
> new Ada.Containers.Vectors (Integer, Integer);
>
> Wrap Element into a function:
>
> V : Integer_Vectors.Vector;
> function Element (Index : Integer) return Integer is
> begin
> return V.Element (Index);
> end Element;
> ...
>
> and use the wrapper.

Sure, but the hope was to write something that does not need new
code for new situations. That's what makes it reusable.

>> Anyway, I am still not sure how to write a generic test for an empty
>> range.
>
> The problem is that the implementation of Cursor that breaks
> abstraction. The abstraction of an argument does not permit ideal
> non-values. Cursors and pointers have non-values. So if you want to test
> for non-values ahead, instead of surprising the function, you need to add a
> test for value validity to the abstraction:
>
> generic
> -- Ordered argument
> type Argument_Type is private;
> with function Valid (Value : Argument_Type) return Boolean is <>;
> ...
> package Generic_Arguments is
>
> Then you would pass Has_Element for it. For integers you would use wrapped
> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
> an object).

It's definitely getting what I call cumbersome.

>> It's possible I was not clear about what I was aiming for. I was hoping
>> to be able to find the maximum of some arbitrary function, taking the
>> function's arguments from any sequential collection.
>
> That is a different abstraction. You need a generic collection instead of
> generic ordered values. E.g.
>
> generic
> with package Arguments is new Ada.Containers.Ordered_Sets (<>);
> with package Values is new Generic_Values (<>);
> package Generic_Comparable_Valued is
> use Arguments, Values;
> function Maximum_At
> ( Domain : Set;
> Func : access function (Argument : Element_Type)
> return Value_Type
> ) return Value_Type;
> -- Other useless functions
> end Generic_Comparable_Valued;
>
> package body Generic_Comparable_Valued is
> function Maximum_At
> ( Domain : Set;
> Func : access function (Argument : Element_Type)
> return Value_Type
> ) return Value_Type is
> Max : Value_Type;
> Value : Value_Type;
> Position : Cursor;
> begin
> if Domain.Is_Empty then
> raise Constraint_Error with "Empty set";
> end if;
> Position := Domain.First;
> Max := Func (Element (Position));
> while Position /= Domain.Last loop
> Position := Next (Position);
> Value := Func (Element (Position));
> if Max < Value then
> Max := Value;
> end if;
> end loop;
> return Max;
> end Maximum_At;
> end Generic_Comparable_Valued;
>
>> Either a simple
>> range of values, an array or vector of values, a list of values or even
>> an ordered map of values -- any ordered list of values.
>
> In practice such abstraction have too much physical and mental
> overhead. E.g. large sets of values implemented differently from
> Ada.Containers.Ordered_Sets depending on the operations required. For
> example, let you need a set complement? Usually programmers simply stick
> with software patterns instead. Too much reliance of libraries make
> programs incoherent.

The core of my Haskell solution is just a function decimalRepeatLength
that returns the repeat length given a divisor. But once I'd got the
answer (by applying it to 2 to 999 and getting the maximum) I wondered
what would happen if the numbers were not in a simple range. Is it easy
to write a `maximisedOver` function that finds the maximum of some
function over any ordered collection (technically, a "foldable" type in
Haskell).

Well, yes, it is easy:

function `maximisedOver` anything = maximum (fmap function anything)

so the solution to the project Euler problem is just

decimalRepeatLength `maximisedOver` [2..999]

but I can also find the maximum of this (or any other suitable) function
over an array, a hash map, a vector... whatever. No code changes
anywhere. It even works with arrays of any number of dimensions
regardless of the index bounds.

maximisedOver is genuinely generic and reusable.

I don't think this is incoherent. The Haskell libraries ensure that any
collection that is logically foldable is indeed foldable.

>> The bottom line is the last argument should be something very general
>> like the Period function.
>> A fix (though it's not really ideal) would be to use function
>> composition here (inventing . as the composition operator):
>> Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>> . Element'Access)
>> but I don't think Ada has a function composition operator, does it?
>
> No as it would require closures.

What closure is required for a function composition? There is no
environment to "close over".

> So you can have a generic composition
> operator, no problem, but not a first-class one. However you can simply add
> Maximum_At with four arguments to the package.

This may be the closest we can get with Ada.

>> Another solution would be to write Maximum_At so that it knows it has a
>> cursor argument, but then I don't think it would work for native arrays,
>> would it? And we'd loose plain ranges altogether.
>
> You can write a generic package creating array cursors:
>
> generic
> type Index_Type is (<>);
> type Element_Type is private;
> type Array_Type is array (Index_Type range <>) of Element_Type;
> package Array_Cursors is
> type Cursor is private;
> function First (Container : Array_Type) return Cursor;
> function Element (Position : Cursor) return Element_Type;
> function "<" (Left, Right : Cursor) return Boolean;
> ...
> private
> package Dirty_Tricks is
> new System.Address_To_Access_Conversions (Array_Type);
> use Dirty_Tricks;
> type Cursor is record
> Domain : Object_Pointer;
> Index : Index_Type;
> end record;
> end Array_Cursors;
>
> package body Array_Cursors is
> function "<" (Left, Right : Cursor) return Boolean is
> begin
> if Left.Domain = null or else Left.Domain /= Right.Domain then
> raise Constraint_Error with "Incomparable cursors";
> end if;
> return Left.Index < Right.Index;
> end "<";
>
> function Element (Position : Cursor) return Element_Type is
> begin
> if Position.Domain = null or else
> Position.Index not in Position.Domain'Range
> then
> raise Constraint_Error with "Invalid cursor";
> else
> return Position.Domain (Position.Index);
> end if;
> end Element;
>
> function First (Container : Array_Type) return Cursor is
> begin
> if Container'Length = 0 then
> raise Constraint_Error with "Empty array";
> else
> return (To_Pointer (Container'Address), Container'First);
> end if;
> end First;
>
> end Array_Cursors;


Click here to read the complete article
Re: project euler 26

<udedrj$3bt69$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10020&group=comp.lang.ada#10020

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: bauhaus@notmyhomepage.invalid (G.B.)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Fri, 8 Sep 2023 08:09:55 +0200
Organization: A noiseless patient Spider
Lines: 21
Message-ID: <udedrj$3bt69$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk>
Reply-To: nonlegitur@notmyhomepage.de
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 8 Sep 2023 06:09:55 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="4f0b5417a67fb6014c2ccf9640695d36";
logging-data="3536073"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+FRCnZX4RMmdJLp8uPYDK4PqizeNPazQI="
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0)
Gecko/20100101 Thunderbird/102.15.0
Cancel-Lock: sha1:cqaF+xwhbvUuyl5wD6VK3mldDKI=
In-Reply-To: <87o7ieq3ne.fsf@bsb.me.uk>
Content-Language: en-US
 by: G.B. - Fri, 8 Sep 2023 06:09 UTC

On 07.09.23 01:32, Ben Bacarisse wrote:

> A fix (though it's not really ideal) would be to use function
> composition here (inventing . as the composition operator):

Hm. A stateful, composed function that needs to be applied
in a certain way. Is that so different from calling interface
subprograms of a certain type?

A wild guess: only "monads" would add substantial toppings
to the commonalities. Considering the computational powers of
C++'s "hair-raising template metaprogramming" [14.4], the idea
of "Ada generics" = "functional style" is probably limited
in scope.

So, does type composition help?

[14.4]: A Tour of C++, 3rd ed.

Re: project euler 26

<udei51$3cfd9$1@dont-email.me>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10021&group=comp.lang.ada#10021

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: mailbox@dmitry-kazakov.de (Dmitry A. Kazakov)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Fri, 8 Sep 2023 09:23:13 +0200
Organization: A noiseless patient Spider
Lines: 110
Message-ID: <udei51$3cfd9$1@dont-email.me>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk> <udc3id$2u9g8$2@dont-email.me>
<8734zpo3fz.fsf@bsb.me.uk>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Fri, 8 Sep 2023 07:23:13 -0000 (UTC)
Injection-Info: dont-email.me; posting-host="58fa476a7c15b05a127e12ddc7037961";
logging-data="3554729"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+RfISsg3mXd/FeDkw2E0GSWC5Me8b/30g="
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101
Thunderbird/102.15.0
Cancel-Lock: sha1:97s7SpA+iCoQQcgz0OYioVe/SDU=
In-Reply-To: <8734zpo3fz.fsf@bsb.me.uk>
Content-Language: en-US
 by: Dmitry A. Kazakov - Fri, 8 Sep 2023 07:23 UTC

On 2023-09-08 03:32, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>
>> On 2023-09-07 01:32, Ben Bacarisse wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>
>>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>>
>>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>>> that:
>>> test2.adb:97:05: error: instantiation error at line 12
>>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>>> It would seem that vector cursors can't be compared using < (at least by
>>> default). Maybe the installation needs more arguments.
>>
>> Vector has a proper index type. All you have to do is. Given
>>
>> package Integer_Vectors is
>> new Ada.Containers.Vectors (Integer, Integer);
>>
>> Wrap Element into a function:
>>
>> V : Integer_Vectors.Vector;
>> function Element (Index : Integer) return Integer is
>> begin
>> return V.Element (Index);
>> end Element;
>> ...
>>
>> and use the wrapper.
>
> Sure, but the hope was to write something that does not need new
> code for new situations. That's what makes it reusable.

Why should it be? You wanted to find maximum of a function. Vector is
not a function. It is in mathematical terms, but not in the language
terms. The abstraction for finding maximum in a container is just a
different abstraction.

>> Then you would pass Has_Element for it. For integers you would use wrapped
>> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
>> an object).
>
> It's definitely getting what I call cumbersome.

Yes, because you try too hard to make it work where it probably should not.

> I don't think this is incoherent. The Haskell libraries ensure that any
> collection that is logically foldable is indeed foldable.

Ada arrays and library containers do not share interfaces. [It is a long
discussion how they could be]. But similarly, there is no shared
interface between digits of a number in octal base and a container and a
string in UTF-16 encoding. Should there be? No. Should the language
allow adding ad-hoc interfaces to existing types. Yes, and this is
possible in Ada in some very uncomfortable AKA cumbersome way, which is
why "finding maximum" is not a worthy abstraction in Ada.

>>> The bottom line is the last argument should be something very general
>>> like the Period function.
>>> A fix (though it's not really ideal) would be to use function
>>> composition here (inventing . as the composition operator):
>>> Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>>> . Element'Access)
>>> but I don't think Ada has a function composition operator, does it?
>>
>> No as it would require closures.
>
> What closure is required for a function composition? There is no
> environment to "close over".

In Ada a function can use anything visible at its declaration point and
at the location of its body. You can even declare a function inside a
recursively called function and let it see local variables of each
recursive call, in effect having an infinite set of functions.

> That's a lot just to use something that is supposed to be reusable.

[rant on]
An Ada programmer would just write a loop. Abstractions are meant to
abstract the problem domain. If you starting abstract elementary
programming activities, then there might be something wrong with the
language or with you.

Then there is a point about readability. When I see a loop I say, aha
this is what the guy is going to do. When I see a pile of calls of a
dozen generic instances with arbitrary names, I begin to worry.

In my view it is a road to nowhere, for an imperative language at least.
The end of this road can be seen in modern C++. 20 years ago C++ was
severely crippled broken but sometimes enjoyable language. You could
*read* a C++ program. In these days with all libraries it became Forth
on steroids. There is no such thing as a C++ program anymore, just calls
upon calls.
[rant off]

> It only occurred to me after writing the non-generic solution. I
> remember Ada as being something of a pioneer in it's attempt to provide
> generic solutions, so I wondered how far things had come. I don't think
> something really widely reusable is possible in this case.

As I said you think in a wrong direction of abstracting the language
"finding maximum" rather than the problem space, e.g. generalization to
other bases, other mathematical structures etc.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Re: project euler 26

<87tts4ml8z.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10022&group=comp.lang.ada#10022

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Fri, 08 Sep 2023 22:02:36 +0100
Organization: A noiseless patient Spider
Lines: 43
Message-ID: <87tts4ml8z.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk> <udedrj$3bt69$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="b39237310d6b9749d50605be679823cd";
logging-data="3894748"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18z8KG8Jur2whZJXuj19m/V18Vz7Qjmknk="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:R9BKgnKwPMGUGntiSJybTkOw4pA=
sha1:e/JS1d9bVkeLrO7ulDXR3a+NvT8=
X-BSB-Auth: 1.808533b7bfad398745e4.20230908220236BST.87tts4ml8z.fsf@bsb.me.uk
 by: Ben Bacarisse - Fri, 8 Sep 2023 21:02 UTC

"G.B." <bauhaus@notmyhomepage.invalid> writes:

> On 07.09.23 01:32, Ben Bacarisse wrote:
>
>
>> A fix (though it's not really ideal) would be to use function
>> composition here (inventing . as the composition operator):
>
> Hm. A stateful, composed function that needs to be applied
> in a certain way. Is that so different from calling interface
> subprograms of a certain type?

There was nothing stateful (as I understand the term) in either function
being composed.

As to your question, not being an Ada expert I can't answer. I could
not see any fix other than passing a composed function which would, it
seems, have to be written afresh. Is that what your question refers to?
If so, then yes there is a small difference: writing a function (albeit
just a few lines) vs. applying an operator to two already written
functions.

> A wild guess: only "monads" would add substantial toppings
> to the commonalities. Considering the computational powers of
> C++'s "hair-raising template metaprogramming" [14.4], the idea
> of "Ada generics" = "functional style" is probably limited
> in scope.
>
> So, does type composition help?

My turn to guess now: you are not being serious? I see no connection to
monads or type composition. And why bring C++ into it?

Having found the maximum of the function 'Period' over a range 2..999,
you might find yourself a week later wanting the maximum absolute value
of the numbers in an Ordered_Map. And then later the maximum of sine
squared over the elements of 2D array. You might want to have a
resuable "maximum of F over X" function, so I was curious about how
close one could get to this in Ada (or, more accurately, what the
restrictions on X and F might have to be).

--
Ben.

Re: project euler 26

<87a5twmbum.fsf@bsb.me.uk>

  copy mid

https://www.rocksolidbbs.com/devel/article-flat.php?id=10023&group=comp.lang.ada#10023

  copy link   Newsgroups: comp.lang.ada
Path: i2pn2.org!i2pn.org!eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: ben.usenet@bsb.me.uk (Ben Bacarisse)
Newsgroups: comp.lang.ada
Subject: Re: project euler 26
Date: Sat, 09 Sep 2023 01:25:37 +0100
Organization: A noiseless patient Spider
Lines: 144
Message-ID: <87a5twmbum.fsf@bsb.me.uk>
References: <c343abf6-3d20-4493-90e5-a317c6829cb2n@googlegroups.com>
<klls16F37qbU1@mid.individual.net> <ud4j5l$1fo57$1@dont-email.me>
<878r9mudvj.fsf@bsb.me.uk> <ud5amn$1jkrc$1@dont-email.me>
<87a5u1u1yv.fsf@bsb.me.uk> <ud5gh7$1kigc$1@dont-email.me>
<8734ztttpc.fsf@bsb.me.uk> <ud6l23$1sq44$1@dont-email.me>
<87fs3ssl6v.fsf@bsb.me.uk> <ud7nba$22ejn$1@dont-email.me>
<87a5u0rts0.fsf@bsb.me.uk> <ud98do$2dbqr$1@dont-email.me>
<87jzt3qqlb.fsf@bsb.me.uk> <uda7c7$2ids2$2@dont-email.me>
<87o7ieq3ne.fsf@bsb.me.uk> <udc3id$2u9g8$2@dont-email.me>
<8734zpo3fz.fsf@bsb.me.uk> <udei51$3cfd9$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Info: dont-email.me; posting-host="af15565c84ea4ea7db7cc714af21fb35";
logging-data="3956740"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/XZhQ/puiU45paw4s0lbWREbP7p8bKh6g="
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.2 (gnu/linux)
Cancel-Lock: sha1:mcxWnvA043/1MEsS1QPrnQlMK4M=
sha1:xnoptaDWXoES689DK3ujemSXkhc=
X-BSB-Auth: 1.441a38024282ca9409e9.20230909012537BST.87a5twmbum.fsf@bsb.me.uk
 by: Ben Bacarisse - Sat, 9 Sep 2023 00:25 UTC

"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-08 03:32, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>
>>> On 2023-09-07 01:32, Ben Bacarisse wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>>>>
>>>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>>>
>>>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>>>> that:
>>>> test2.adb:97:05: error: instantiation error at line 12
>>>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>>>> It would seem that vector cursors can't be compared using < (at least by
>>>> default). Maybe the installation needs more arguments.
>>>
>>> Vector has a proper index type. All you have to do is. Given
>>>
>>> package Integer_Vectors is
>>> new Ada.Containers.Vectors (Integer, Integer);
>>>
>>> Wrap Element into a function:
>>>
>>> V : Integer_Vectors.Vector;
>>> function Element (Index : Integer) return Integer is
>>> begin
>>> return V.Element (Index);
>>> end Element;
>>> ...
>>>
>>> and use the wrapper.
>> Sure, but the hope was to write something that does not need new
>> code for new situations. That's what makes it reusable.
>
> Why should it be? You wanted to find maximum of a function. Vector is
> not a function.

I wanted the maximum of a function over a collection (range, array, map,
etc). In some languages, collections can be scanned so you don't need
to know where the data come from.

>>> Then you would pass Has_Element for it. For integers you would use wrapped
>>> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
>>> an object).
>> It's definitely getting what I call cumbersome.
>
> Yes, because you try too hard to make it work where it probably should
> not.

If you think a resuable Ada function that can find the maximum of some F
over some 'collection' X is possible, I'd like to see how it's done. I
can do it for some kinds of X but I have no idea how general it can be
made in Ada. I think the answer is either that it can't be very
general, or to make it very general is too much work, or that one should
not be trying in the first place.

(I put 'collection' in quotes because I know that's an Ada term but I
don't necessarily want to restrict the solution to how Ada uses the
term. For example, I don't think native arrays are collections in the
formal Ada library sense.)

>> I don't think this is incoherent. The Haskell libraries ensure that any
>> collection that is logically foldable is indeed foldable.
>
> Ada arrays and library containers do not share interfaces.

I was pretty sure that was the case. Thanks for confirming. I think
that means there can be no truly generic solution. But maybe it's
possible at least for all container types in the library? (But I note
that if you think it /shouldn't/ be done, I won't expect you to show me
how.)

> Should the language allow adding
> ad-hoc interfaces to existing types. Yes, and this is possible in Ada in
> some very uncomfortable AKA cumbersome way, which is why "finding maximum"
> is not a worthy abstraction in Ada.

I suspected one might have to extend the interfaces. If a simple
abstraction (maximise F over X) does not have a simple representation,
it's not going to be worth it. Just write a slightly different empty
test and loop each time you need to do it.

>>>> A fix (though it's not really ideal) would be to use function
>>>> composition here (inventing . as the composition operator):
>>>> Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>>>> . Element'Access)
>>>> but I don't think Ada has a function composition operator, does it?
>>>
>>> No as it would require closures.
>> What closure is required for a function composition? There is no
>> environment to "close over".
>
> In Ada a function can use anything visible at its declaration point and at
> the location of its body. You can even declare a function inside a
> recursively called function and let it see local variables of each
> recursive call, in effect having an infinite set of functions.

At the point where I want Period.Element I can write the (almost)
one-line function that takes a Cursor and returns Period(Element(C))
entirely mechanically. Can't the compiler do that?

Note I'm not asking if it /should/ (it may not be "Ada-like" to do
that). I'm just curious if there really is a technical reason it can't
be done.

>> That's a lot just to use something that is supposed to be reusable.
>
> [rant on]
> An Ada programmer would just write a loop.

Yes, that's fine. Different languages have different objectives. Just
write the empty range test and the loop you need for each kind of
collection. That was definitely the way things were done in the 80s.

>> It only occurred to me after writing the non-generic solution. I
>> remember Ada as being something of a pioneer in it's attempt to provide
>> generic solutions, so I wondered how far things had come. I don't think
>> something really widely reusable is possible in this case.
>
> As I said you think in a wrong direction of abstracting the language
> "finding maximum" rather than the problem space, e.g. generalization to
> other bases, other mathematical structures etc.

Generalising to an arbitrary base is local to the function that finds
the answer for one element. It's an entirely separate axis of
generalisation to that of where the elements come from.

It's interesting to me that you consider one simply wrong and the other
natural. In some languages the "wrong" one does not even merit
consideration as it's just there for free. You can concentrate on the
other bases and other structures without worrying if the program will be
able to maximise over the collection in which they are stored. (For
example, for polynomial residues, they can't come from a range like
2..999.)

I really do appreciate your help. I would not have got off the ground
with generics without your examples. Also, one thing I like about
Usenet is coming across people with very different ideas about
programming. In this case, it seems to be about what is worth
generalising and what isn't.

--
Ben.

Pages:12
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor