• use clauses

    From Thomas@21:1/5 to Randy Brukardt on Wed Apr 13 01:25:31 2022
    In article <s5vqq9$lou$1@franka.jacob-sparre.dk>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    For me, a naming scheme that discourages the use of (package) use clauses is a bonus. (Such a scheme makes it easier to avoid use clauses.)

    I agree to avoid use clauses.

    (I personally prefer Lists.List, like Vincent Marciante -
    i like Ada.Containers.* naming :-) )


    I personally
    only use "use type" in new code (there's tons of old code for which that doesn't work, of course, but that doesn't change the principle).

    what do you think about:
    - "use all type" clauses?
    - List.Clear? (could you remember me how you call that, please?)
    - List.Clear does work only if List is tagged?

    --
    RAPID maintainer
    http://savannah.nongnu.org/projects/rapid/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Thomas on Tue Apr 12 20:05:00 2022
    "Thomas" <fantome.forums.tDeContes@free.fr.invalid> wrote in message news:62560a6b$0$18724$426a74cc@news.free.fr...
    In article <s5vqq9$lou$1@franka.jacob-sparre.dk>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    For me, a naming scheme that discourages the use of (package) use clauses
    is
    a bonus. (Such a scheme makes it easier to avoid use clauses.)

    I agree to avoid use clauses.

    (I personally prefer Lists.List, like Vincent Marciante -
    i like Ada.Containers.* naming :-) )


    I personally
    only use "use type" in new code (there's tons of old code for which that
    doesn't work, of course, but that doesn't change the principle).

    what do you think about:
    - "use all type" clauses?

    This is OK; I don't use them mainly because I only use features implemented
    in Janus/Ada, and "use all type" is not yet implemented there.

    The fundamental problem with "use" is that it makes everything visible, and then deals with conflicts by making those things invisible again. That's not problem for overloadable primitive operations, since the profile is included and conflicts only occur when someone has made a lousy design choice
    (creating a routine with the same name and profile as a primitive) [Most
    such conflicts come from maintenance when some existing routine is moved to
    be primitive; in such cases, the original routine simply should be removed.] Since "use all type" only works on overloadable primitives (and things that work rather like primitives), it's fairly safe. One could make an argument
    that primitive operations should always be visible when the type is (that's
    not the Ada rule, but argubly it would work better in most circumstances) -- and you should always know to look at primitives anyway when trying to find something..

    - List.Clear? (could you remember me how you call that, please?)

    For tagged types, you can use prefix notation, so "My_List.Clear" is the easiest. With "use all type List", you can write Clear(My_List). If your objects have well-choosen names, it's not really needed to have the type
    around for such operations, even when use clauses are in place. Thus,
    "Clear", not "Clear_List", and that works well even when someone uses everything in sight (of course, they may have a hard time finding where
    Clear is defined when debugging, but that's their choice).

    - List.Clear does work only if List is tagged?

    Right. There are a number of semantic issues for untagged types, the main
    ones having to do with implicit dereference (which occurs in this notation,
    as in any other selected_component notation). If you have a prefix of an
    access type, it gets very messy to determine which dereference is which. And just allowing composite types doesn't work well either: a private type that
    is completed with an access type would *lose* operations when it had full visibility -- that seems pretty weird.

    It originally got limited to tagged types as that was easy to do and didn't have semantic issues. We were going to look at generalizing the prefix
    notation again (several people asked about it), but no one made a concrete proposal and it never went anywhere for Ada 2022.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From 25.BX944@21:1/5 to All on Wed Apr 13 22:51:01 2022
    After fiddling around with ADA for awhile, I have concluded
    that it's Just Not Worth It - too fiddly, TOO obsessed with
    exact types and such. While there are SOME few justifications
    for that, well, it's just pretty much UNUSABLE. If I need to
    use an "old" language, well, FORTRAN is easier to deal with
    and I actually *like* Pascal (I write lots of stuff in
    Lazarus/FPC even today). And, of course, 'C' ...

    So, unless you are somehow OBLIGATED, use something,
    anything, but ADA.

    Sorry, not what you wanted to hear, but ......

    I will now de-subscribe.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Emmanuel Briot@21:1/5 to All on Wed Apr 13 23:49:13 2022
    On Thursday, April 14, 2022 at 4:51:10 AM UTC+2, 25.BX944 wrote:
    So, unless you are somehow OBLIGATED, use something,
    anything, but ADA.

    I fully understand. Can I recommend that you try Whitespace (https://en.wikipedia.org/wiki/Whitespace_(programming_language)) or Basic as your language of choice ? They should not be as bothersome as Ada. Of course, the surprises come at run time !

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Doctor Who@21:1/5 to All on Fri Apr 15 07:33:07 2022
    On Wed, 13 Apr 2022 22:51:01 -0400, "25.BX944" <25BZ494@nada.net>
    wrote:

    After fiddling around with ADA for awhile, I have concluded
    that it's Just Not Worth It - too fiddly, TOO obsessed with
    exact types and such. While there are SOME few justifications
    for that, well, it's just pretty much UNUSABLE. If I need to
    use an "old" language, well, FORTRAN is easier to deal with
    and I actually *like* Pascal (I write lots of stuff in
    Lazarus/FPC even today). And, of course, 'C' ...

    So, unless you are somehow OBLIGATED, use something,
    anything, but ADA.

    Sorry, not what you wanted to hear, but ......

    I will now de-subscribe.

    you are not a programmer.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas@21:1/5 to Randy Brukardt on Tue Apr 19 05:53:47 2022
    In article <t357jt$v7n$1@dont-email.me>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    "Thomas" <fantome.forums.tDeContes@free.fr.invalid> wrote in message news:62560a6b$0$18724$426a74cc@news.free.fr...
    In article <s5vqq9$lou$1@franka.jacob-sparre.dk>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    I personally
    only use "use type" in new code (there's tons of old code for which that >> doesn't work, of course, but that doesn't change the principle).

    what do you think about:
    - "use all type" clauses?

    This is OK; I don't use them mainly because I only use features implemented in Janus/Ada, and "use all type" is not yet implemented there.

    The fundamental problem with "use" is that it makes everything visible, and then deals with conflicts by making those things invisible again.


    Since "use all type" only works on overloadable primitives (and things that work rather like primitives), it's fairly safe. One could make an argument that primitive operations should always be visible when the type is (that's not the Ada rule, but argubly it would work better in most circumstances) -- and you should always know to look at primitives anyway when trying to find something..

    are you speaking about a case like Ada.Text_IO.Unbounded_IO?
    i would say that these subprograms are not primitives, since they are
    not declared in the same package,
    and i don't see in which case we could get a type visible but not its primitives.

    in this case, the best thing to do that i found is:
    use all type Ada.Text_IO.File_Type;
    use Ada.Text_IO.Unbounded_IO;
    is there sth best?


    BTW, i often get a repetition in the same declare bloc, like:
    File : Ada.Text_IO.File_Type;
    use all type Ada.Text_IO.File_Type;

    what do you think about generate an automatic "use all type" where the
    variable is declared?



    - List.Clear? (could you remember me how you call that, please?)

    For tagged types, you can use prefix notation, so "My_List.Clear" is the easiest. With "use all type List", you can write Clear(My_List).

    i asked for your opinion, because J-P. Rosen told me he doesn't like
    that. so i would like to know main usages, practicals, ...

    if i got it, you use prefix notation a lot, because you have no access
    to "use all type"?


    ["Clear" works well even when someone uses
    everything in sight] (of course, they may have a hard time finding where Clear is defined when debugging, but that's their choice).

    are you sure?
    i would say either there is only 1 Clear for the type List, and if it's
    a primitive it's easy to know where to find it, or there are many Clear
    for the type List, and they are not visibles.



    - List.Clear does work only if List is tagged?

    Right. There are a number of semantic issues for untagged types, the main ones having to do with implicit dereference (which occurs in this notation, as in any other selected_component notation). If you have a prefix of an access type, it gets very messy to determine which dereference is which. And just allowing composite types doesn't work well either: a private type that is completed with an access type would *lose* operations when it had full visibility -- that seems pretty weird.

    It originally got limited to tagged types as that was easy to do and didn't have semantic issues.

    what's i don't understand is, there is sth which work better with tagged
    types than with untagged types, whereas tagged types are known to be
    more complex to give special functionnality, not to be simpler to use.

    could you give me a concrete example please, of a case where using
    prefix notation with an untagged type causes a particular problem, and
    then making the type tagged permits to resolve the problem?


    We were going to look at generalizing the prefix
    notation again (several people asked about it), but no one made a concrete proposal and it never went anywhere for Ada 2022.

    (maybe i could make one if i understand enough? :-) )

    --
    RAPID maintainer
    http://savannah.nongnu.org/projects/rapid/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Thomas on Tue Apr 19 00:59:31 2022
    "Thomas" <fantome.forums.tDeContes@free.fr.invalid> wrote in message news:625e324c$0$18369$426a34cc@news.free.fr...
    In article <t357jt$v7n$1@dont-email.me>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    "Thomas" <fantome.forums.tDeContes@free.fr.invalid> wrote in message
    news:62560a6b$0$18724$426a74cc@news.free.fr...
    In article <s5vqq9$lou$1@franka.jacob-sparre.dk>,
    "Randy Brukardt" <randy@rrsoftware.com> wrote:

    I personally
    only use "use type" in new code (there's tons of old code for which
    that
    doesn't work, of course, but that doesn't change the principle).

    what do you think about:
    - "use all type" clauses?

    This is OK; I don't use them mainly because I only use features
    implemented
    in Janus/Ada, and "use all type" is not yet implemented there.

    The fundamental problem with "use" is that it makes everything visible,
    and
    then deals with conflicts by making those things invisible again.


    Since "use all type" only works on overloadable primitives (and things
    that
    work rather like primitives), it's fairly safe. One could make an
    argument
    that primitive operations should always be visible when the type is
    (that's
    not the Ada rule, but argubly it would work better in most
    circumstances) --
    and you should always know to look at primitives anyway when trying to
    find
    something..

    are you speaking about a case like Ada.Text_IO.Unbounded_IO?

    No, I was thinking more about typical ADTs (abstract data types), which
    usually come with most of their operations in a package. The containers, Text_IO, and Claw are all examples. Operations in packages like this are the ones that "use all type" make visible, and that's OK because that's where
    you would look for operations on the type anyway.

    i would say that these subprograms are not primitives, since they are
    not declared in the same package,

    Correct.

    and i don't see in which case we could get a type visible but not its primitives.

    The primitives and type are visible, but not directly visible (I hate that terminology). Which means you can use them with full names, but not
    directly. For types, I almost always use the full name anyway (since they aren't referenced that much). So if you have an object:

    Fyle : Ada.Text_IO.File_Type;

    the type is visible (but not directly visible). It's annoying that you have
    to jump thru hoops (such as "use all type") in order to get them. Operators
    in particular should always work so long as the type is visible (even if not directly visible). But that would require restricting where they are
    declared, and it's too late to do that for Ada.

    in this case, the best thing to do that i found is:
    use all type Ada.Text_IO.File_Type;
    use Ada.Text_IO.Unbounded_IO;
    is there sth best?

    I just write out such things.

    Ada.Text_IO.Unbounded_IO.Put (My_String);

    If I had to use a lot of them in some code, I'd probably use a local rename. It's not great, but at least you can figure out where the thing is declared without having some giant IDE running all the time..

    BTW, i often get a repetition in the same declare bloc, like:
    File : Ada.Text_IO.File_Type;
    use all type Ada.Text_IO.File_Type;

    Yup.

    what do you think about generate an automatic "use all type" where the variable is declared?

    For tagged objects, you already have it effectively with prefix notation.
    And who cares about antique stuff?? :-)

    - List.Clear? (could you remember me how you call that, please?)

    For tagged types, you can use prefix notation, so "My_List.Clear" is the
    easiest. With "use all type List", you can write Clear(My_List).

    i asked for your opinion, because J-P. Rosen told me he doesn't like
    that. so i would like to know main usages, practicals, ...

    if i got it, you use prefix notation a lot, because you have no access
    to "use all type"?

    Nope: Janus/Ada doesn't implement that yet, either (it was an Ada 2005 feature). I personally write a lot of long-winded identifiers:

    Foobar (UString => Ada.Strings.Unbounded.To_Unbounded_String (My_Package.Data_Selector (Glarch, 3));

    (Although that one often gets a special rename:

    function "+" (A : in String) return
    Ada.Strings.Unbounded.Unbounded_String renames
    Ada.Strings.Unbounded.To_Unbounded_String;

    and then:

    Foobar (UString => + My_Package.Data_Selector (Glarch, 3));

    I'd rather not do that, but this one gets to be too much... :-)

    ["Clear" works well even when someone uses
    everything in sight] (of course, they may have a hard time finding where
    Clear is defined when debugging, but that's their choice).

    are you sure?
    i would say either there is only 1 Clear for the type List, and if it's
    a primitive it's easy to know where to find it, or there are many Clear
    for the type List, and they are not visibles.

    The usual problem is that they didn't name their objects very well and thus don't know the type. Or it's maintenance and you don't know the code well enough to know the type. Or it's 40 years later and you've forgotten
    everything you knew about the code (my situation with Janus/Ada code :-). If you don't know the type or know where it it declared, it's hard to know
    where to look for primitives. And not all code is organized as ADTs
    (especially true in older code), so there may not be a lot of primitives.

    - List.Clear does work only if List is tagged?

    Right. There are a number of semantic issues for untagged types, the main
    ones having to do with implicit dereference (which occurs in this
    notation,
    as in any other selected_component notation). If you have a prefix of an
    access type, it gets very messy to determine which dereference is which.
    And
    just allowing composite types doesn't work well either: a private type
    that
    is completed with an access type would *lose* operations when it had full
    visibility -- that seems pretty weird.

    It originally got limited to tagged types as that was easy to do and
    didn't
    have semantic issues.

    what's i don't understand is, there is sth which work better with tagged types than with untagged types, whereas tagged types are known to be
    more complex to give special functionnality, not to be simpler to use.

    could you give me a concrete example please, of a case where using
    prefix notation with an untagged type causes a particular problem, and
    then making the type tagged permits to resolve the problem?

    Go read the AIs, I would have to do that to find the details, and I'd
    probably transcribe it wrong. The last discussion was in AI12-0257-1. (I
    looked that up in the AI index - see
    http://www.ada-auth.org/AI12-VOTING.HTML for the Ada 2012 one.)

    We were going to look at generalizing the prefix
    notation again (several people asked about it), but no one made a
    concrete
    proposal and it never went anywhere for Ada 2022.

    (maybe i could make one if i understand enough? :-) )

    That's a big if! :-)

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)