What's your experience with using % for accessing object members?

With this code in a foo.el file, and after M-x load-file “foo.el” in Emacs

(font-lock-add-keywords
 'f90-mode `(
             ("\\(\%\\)"
              (0 (progn (compose-region (match-beginning 1)
                                        (match-end 1) "•")
                        nil))
)))

I get something that looks like


There are only % in the source file.

6 Likes

I find this argument unconvincing, given that Fortran is case insensitive. You may as well write car%startengine(), to give you a small visual bump from the %.

You could also use free functions, instead of type-bound functions:

call start_engine(car)  ! snake_case
call car%StartEngine()  ! CamelCase

With syntax highlighting for the % token and a suitable font, I find the visibility is good enough. At least it’s never been a problem for me. This is what my set up looks like in Sublime Text using the Monokai color scheme and the IntelOne Mono font, developed with “a panel of low-vision and legally blind developers [who] provided feedback at each stage of design”:

As you can see the grammar I’m using doesn’t correctly highlight the type-bound method call.

I do think your thread raises an interesting question if Fortran could benefit from a custom font. For example instead of regular monospaced font, it could make % 1.5× the default width. I’ve seen something like this done before in the iA Writer app:

Source: From Monospace to Duospace: In Search of the perfect writing font

4 Likes

With Kate, I can’t miss it in both cases:
image

3 Likes

I guess you are using the Fortran package.
I would say the issue stands in the fact that the call-statement regex definition

call_statement:
    - match: |
        (?xi)
        (?:
          \b  (call)
          \s+ (?: ({{ident}}) \s* % \s* ({{ident}})
                | ({{ident}})
              )
        )
      captures:
        1: keyword.call.fortran
        2: variable.other.fortran
        3: support.function.any-method
        4: support.function.any-method

comes before the one related to arithmetic operators

arithmetic-operators:
    [...]
    # type member access
    - match: \%
      scope: keyword.operator.member-access.fortran

The second saying that, everytime you encounter an %, colour it whatever.
But, by the time the call statement is captured, since it covers the whole line, it prevents the former to kick in. So, the difference.

I remember at some point I had written my own custom Sublime syntax highlighting scheme, by modifying those rules. I am since then not using sublime anymore for other reasons, and apparently now it’s a lot harder to get to apply its own modifications to the package file.
If you regularly use Sublime, and if that bothers you, I think you could open an issue on the GitHub page, where I guess a simple displacement of the call-statement regex under the arithmetic-operators one should quickly solve this specific issue.

At least, said by heart memories.

How to set such highlighting rule in Kate?

I don’t like the aesthetics of the % symbol, but it was chosen for valid reasons. To me, the annoying part of foo%num_atoms is not the % but the whole foo%, which mucks up mathematical formulas terribly. In formula-dense code, I tend to end up unpacking the derived type’s components using local variables/pointers/associate. Otherwise, there’s just too much foo% noise to make any sense of what’s going on.

4 Likes

Pascal with rules!
https://smartpascal.github.io/help/assets/with.htm

1 Like

Kubuntu 23.04:

  • It’s the default highlighting for Fortran in my Kate 22.12.3.
  • In Geany, % is also highlighted in both cases, but in brown by default, which is not very distinct (to say the least).
  • In Vim, it is never highlighted.

I have found that file: /usr/share/kde4/apps/katepart/syntax/fortran.xml
but I can not find the % character inside…
But the rose color is the same as for comparison operators like == /= <= >=, etc.

How many of you use custom operators in your codes?

I personally never use them.

And if you use them, how many of you do not put spaces around them? That is, do you ever use x.foo.y, or do you always write x .foo. y if .foo. is a custom operator?

I think it’s possible to design such rules that disambiguate . in all cases (sometimes you must insert some parentheses to disambiguate, but most common cases just work), see this comment for one such set of rules: Idea: Support dot (`.`) as an alternative to the `%` operator (#84) · Issues · lfortran / lfortran · GitLab. There are other possibilities, such as using the space around .foo. as significant.

I am with you about the argument of not being worth to change at this point (I am undecided). But Fortran absolutely fixed bad syntax in the past, here are some examples:

  • replacing (/1, 2, 3/) to [1, 2, 3]
  • replacing arithmetic if with regular if
  • replacing “label continue” with “end do”
  • replacing for all with do concurrent

and many other such things. Those were all cases where an equivalent (duplicate) syntax was introduced, and the new syntax gradually took over. Strictly speaking sometimes the semantics was slightly different too. So . might have slightly different rules from % how it is parsed, but as long as it works in all common cases and as long as there is a robust way to disambiguate, I think it can work and it is not something that Fortran has never done before.

For me the most compelling reason to do this is the number of times I’ve seen a new Fortran user ask precisely this question, or even what exactly the % operator does.

1 Like

Would x.(foo).y be possible instead of (x).foo.(y)?

It feels much easier to me to create this disambiguation using x.(foo).y

Custom operators could be quite useful for some complicated mathematical operations, where nothing else would be an option, so keeping them would be useful.

I have to learn more about them to have a more educated opinion about them.

1 Like

I never use custom operators.
But when using logical operators, I am writing x.foo.y as I consider that the points are graphically sufficiently equivalent to spaces (I mean they are small symbols on the bottom of the line).

1 Like

Arf, we are still with debian 9 and Kate versions from the Stone Age. We have a few machines with Debian 11, I will check if the default Kate does the trick.

@vmagnin felt that introducing a second syntax for the same thing would just add confusion. But for 20 years now (/ /) and [ ] have been two syntaxes for the same thing that do not.

1 Like

But if . is used to denote components, with the appropriate restrictions regarding surrounding spaces and such to disambiguate from operators, then there would be two ways to denote component syntax. Then beginners would be even more confused than they are now.

I personally would have preferred @ to denote components. It stands out, and it seems to me to be self describing, perhaps even more so in modern times where @ is used in internet addresses. However, @ was not in the f77 character set (nor in the f90 character set for that matter), so the committee went with % instead. At this point in time, I think it would be counter productive to introduce a new redundant syntax into the language, and it would certainly be a bad idea to introduce a new component symbol and declare the old one obsolete.

I think I only went for it when learning about OOP, found it nice but then never had an actual reason to use them.

:thinking: this sounds compelling. I also had that rough patch making peaces with % then learned to live with it. (Yet, I found it clearer than ->)

1 Like

With the caveat that they can only take two arguments, they actually do solve problem often mentioned. You can’t chain type-bound procedures, but you can chain type-bound operators. I.e.

things = set(stuff).union.set(more).intersection.set(others)

And if you do want to have more than two arguments, you can define a derived type to hold the extra “arguments”. I.e.

thing = dict.with.entry(key, val).get.with_default(other_key, default_val)

Another neat example (which my quaff library actually supports) would be something like

dist = 100.unit.miles.in.kilometers
14 Likes

If the “custom operator” of @certik is what the Fortran standard and Modern Fortran Explained call a “defined operator” then I found .X. and .dot. somewhat useful to define the vector and scalar products of two vectors (arrays with 3 real elements). Fortran does not have the feature that Algol 68 had, of giving defined operators the same precedence as * (multiplication). That is why I said “somewhat” and had to be very careful with parentheses.

1 Like

I think it is the first time ever I strongly disagree with you. :slight_smile: Currently custom operations are the only way to circumvent the terrible restriction of inability % to() % do() % chain() % calls. They allow you to at least partially .build. "nice interfaces" .in. "this language". And, as I said, they are the unique feature of the language, which some papers used very creatively.

Dot is the least of our issues.

Edit: did not read the whole thread before replying, but basically everything was mentioned here.

1 Like

I’m all for breaking backward compatibility to remove nonsense and malicious legacy syntax. But I never thought the % was that big of a deal. Sure . would have been better, but it think it’s just too late. It’s something that seems weird the first time you learn it but then you just accept it and move on. Make sure your IDE syntax highlighter makes it a different color and it’s not hard to see. It never bothered me the way having to type implicit none all over the place does.

It’s far superior to any two character alternative (…, ::, ->). Note that .. is already used in Fortran for the rank thing.

6 Likes

@gronki so the main motivation for the .custom_op. syntax is to fix the deficiencies of the % operator (which really should be the “.” operator)?

That seems like fixing a symptom instead of the issue.