Idea: Enhance the length operator

:dart:

    

I would rather implement this one, if it would not clash with the existing compare operator.

I’m not sure I see any clash, simply an overlap, but it does point to a part of the argument not made explicitly above:

It is simple to combine a number of single-purpose functions into more complex forms. Thus we have length[]compare:number:gt[5] or length[]match[0] If we wanted to do similar things with list counts, we could just do count[]compare:number:gt[5] or count[]match[0]. But if we start with lengthGT[5], we will not be able to apply this to list counts. Simpler functions are more easily composed.

This does not prevent us from building up our own lengthGT functions. But it’s the building blocks we want to make public.

The famous Perlis quote is at least somewhat relevant, and always worth re-reading:

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. – Alan Perlis

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures. – Alan Perlis

Fun fact: In 1980/81 as a freshman at Carnegie-Mellon University, I took Intro to Software Engineering, taught by Prof. Perlis. The next semester, he hired me as a “tutor/grader” for the course. Really nice guy.

-e

3 Likes

Oh, then by all means, we really should list some of our favorite of his wonderful quotes. I’ll start.

The best book on programming for the layman is Alice in Wonderland, but that’s because it’s the best book on anything for the layman.

I appreciate that, but I too have a long experience, including coding, and user readable perspectives. One of my cultivated skills is translating between IT and Business and back again.

Whilst I do understand and largly support your argument from code simplicity etc… I think it is a matter of scale and semantics. In some ways the objections you give such as the example [<input>length:Helvetica:14pt:cm[]] is what seems like a “slipery slope” aregument. I am not proposing such a thing.

I am, only proposing the length[] operator who’s parameter is “unused be” extended to not only return the length (constructor), but allow it to only return titles of length[n] (selector).

You see this is perhaps where I differ, to me length[] asks for a length number and length[5] sets the number so acts as a filter. if the number is specified, it can hardly be asking to return a number.

  • length[] is like count[]
  • length[4] is like match[4]
    To put it in your terms “I can comfortably know what it returns”.

It remains exactly related to root question, but needed to be opened up to a design or coding discussion about frugality (use one operator to do two related things) vs single function operators (to maintain a coding ideal).

  • Something which arguably makes sense to discuss, but needs an example to make it possible to discuss, in this case the length operator.

The bigger picture;

I have not put the reason for this desire to simplify the writing of filters with a more “functional” length operator, because I would just have made this more complicated. Here is a hint.

  • I have developed a method to look at a string and determin a format template for it. For example NNNNNNNNNNNNNNN would indicate a TiddlyWiki date time stamp. But of course this can be represented with length[15].
  • This approach is much easier than needing additional operators, especially when I may be testing multiple parts of the same string.

One of my goals with BASIC Anywhere Machine: compatibility with GW-BASIC.

If I did not care about that compatibility, I’d definitely be getting rid of multi-purpose features in functions because it makes for messy implementation code.

For example: POINT.

POINT (x,y) returns the colour at the pixel coordinate.

POINT(0) and, alternatively, POINT(2) gives the current x coordinate resulting from the last graphics statements.

POINT(1) and, alternatively, POINT(3) gives the current y coordinate resulting from the last graphics statements.

I would never have implemented POINT that way. It is a lousy idea.

That, however, is not the worst of it.

It is the messy code related to implementation:

if (name=='point') {
          Skip('(');
          var a = Expression();
			 if (tok==',') {
            Skip(',');
            var b = Expression();
            Skip(')');
            return 'Point(('+a+'), ('+b+'))';
			 }
			 else {
			   Skip(')');
            return 'PointPos('+a+')';
			 }
        }

In the grand scheme of things, any developer could figure out what is going on there.

However…

Code that is intertwingled makes for risky code. It makes for less robust code and increases risk of problems going forward, problems that increase in likelihood when a project can have who knows how many people updating/adding/touching the code (I.e. TW core).

Clean and focused implementation code wins the day.

But it is only a few lines of code? Well …

What you are suggesting for length[] is the kind of stuff that adds another dime to a nickel and dime mess to the code that makes TW work.

I’m against that kind of change to length[] because I have zero-tolerance for things that create risk to stability. With all due respect to the talent on TW development: even if all of them are the world’s elite programmers, I insist on solid and very focused segments of code.

What you are asking for re length, it should be a new and dedicated operator for that functionality. Otherwise, I’m going to have some significant reservations about the thought-processes behind TW development.

Keep the TW code clean and focused.

I suppose then I need to agree to disagree, to me code can be used to hide the complexity, a “complex” piece of code, to make a simpler filter operator, that is itself much more functional, looks more like plain language and is easy to read.

  • No doubt we agree in many aspects of this issue, and approach, but I draw a different conclusion in these circumstances.

This would be wrong in my view, to think this way, based on a small detail for which there are arguments either way. I am not developer, I am a contributor. I started this thread and illustrated, from the outset how this is something I would like to see to simplify its use.

Never the less thanks for answering;

Here is my stringlength filter operator that does as I like. Once installed save and reload for it to work. It is self documented in the installed tiddler as follows;

stringlength

A filter operator that either compares the length of a title to a specified number,
or returns the length of each title when no parameter is given.

Usage Example in TiddlyWiki Filters

  • [stringlength[]]: Returns the lengths of all titles as strings.
  • [stringlength[5]]: Returns all tiddlers with titles exactly 5 characters long.
  • [!stringlength[5]]: Returns all tiddlers with titles not 5 characters long.

The stringlength operator is more versatile than the length operator, allowing it to serve both as a filter based on string length and as a tool to simply report the lengths of strings.

stringlength.json (2.1 KB)

I acknowledge with the help of ChatGPT :nerd_face:

We already have the minlength[n] operator, which would be the same as length:gteq[n], no?
We could propose either maxlength[n] or !minlength[n] to mean something like length:lteq[n]. If we want to check for length n exactly, we’d have to chain minlength[n]maxlength[n].

Personally, I don’t mind writing length[]compare:number:gt[n], it’s very semantic. However, I’d like number to be the default for the compare type, since it’s probably the most-used; compare::gt[n] would keep my filter expressions so much shorter.

Having a look at the code. “number” is the default.

I did create a PR to improve the docs: Add type "number: (default)" to compare operator by pmario · Pull Request #8160 · Jermolene/TiddlyWiki5 · GitHub

Thanks @Yaisog for your reply. However in this case and what my stringlength operator and suggested enhancement to length was to return only strings of length N, ie equal length. The idea is to allow us to do things like test numbers and other strings are of a specified length, eg date stamp, month number, phone number etc…

  • I would have this for a larger set of tools to allow us to test a users input, that it matches a particular format. Or divide a string into pieces and test its component lengths, to either use it to convert incoming content, and other string manipulations.
    • In this case such length tests may be numerous, and having to use length[]compare:number:eq[n] as opposed to length[n] will be overly verbose.
      • Note how my proposal suggests to start using a parameter we don’t currently use and no more?
    • Although so as to not “ruffle feathers” I have long suggested I would make use of my own operator stringlength[] and stringlength[n] as shared above.
      • My experience suggests with TiddlyWikis focus on titles in filters, we have somewhat neglected string handling, ie; what a title is when its not an actual tiddler title. I would like to remedy that and build up the components to make strings and formatting much easier. I did not want to start with a fundamental feature, needing to use compound and verbose filters.
  • In a very similar approach, I already have an operator under development, stringformat[] that given the input 1234abcd_ generates a format like NNNNAAAAS (N=numeric, A = alphabetic, S = special or other characters)
    • eg;[[4321defg_]stringformat[]] output of NNNNAAAAS.
    • and once you have this format you can test an input eg;[[4321defg_]stringformat[NNNNAAAAS]] and only if the input matches the format will the input be passed on.
    • Ideally, also the !stringformat[NNNNAA] form.

In both of the above the filter operator has one behaviour with a missing parameter, and a complementary behaviour with the parameter given.

Perhaps [[input]compare:length:eq[n] to use rather than [[input]length[]compare:number:eq[n] ?

Thanks for pointing this out!

In that case, length[]compare::eq[n] has all the brevity and flexibility I could ever need. I don’t think there would be much gained by creating new operators that do the same thing with only a few fewer letters.

There is no way anybody is going to get you to change your mind, just like there is no way anybody is going to change my mind.

The prudent approach: when there is no consensus on making some kind of change to TW core, then that change should not happen. TW stability and maintainability should never be a trade-off for the sake of a feature that could be implemented as a new operand (or, better: as an add-on function in a library that each person can drag into their TiddlyWiki like a plugin).

If you are going to keep pursuing that change to TW core, then I’m going to keep voicing my disagreement.

Of all my challenges with things added to TW since version 5.2.3 and all of my challenges with TiddlyTalk vs Google Groups, this is strangely the hill I’ll die on. Your request to change length is the kind that triggers me, has always triggered me, and will always trigger me.

So if we must keep locking horns over this, then it is what it is. If you can’t let it go, then such is your condition and such is your burden, and I easily accept that because I understand that. I also can’t let it go, because such is my condition and such is my burden (my experience and my values).

EDIT: I’m assuming here you are still pushing for a TW-core change to the length operator as per your OP. If you are intending on creating a new custom function that you can share with everybody, I think that’s great (I’ve got no issue with that because I consider custom add-ons very good stuff.)

@TW_Tones There’s nothing wrong with creating your own operators. Instead of pushing them into the core, you could also package them as a plugin and offer them to any interested parties. That’s what I do with my more specialized ones.

2 Likes

Good point Scott, I just realised I did not reply, its true the result would be different, if a variable was used and the parameter as a variable invalid, a number would pop out rather than title, but this would most likely also happen with any other filter used instead.

  • Just let me reinforce, I wanted to see what people think, not insist on anything.
  • You don’ know that about me, nor is it important that “I change my mind”, this just a conversation.

Please I think you could just let it go @Charlie_Veniot, I am prepared to, I hope you are. I have a different view to you, I have not insisted on core change and gone my own way. I only extended this conversation, because I disagree with your response to my suggestions and just thought you did not seem to see how simple and I believe, appropriate, the change I proposed.

  • I thought you had not understood, not that it was a “position” you were taking.

I know you come from a different perspective, perhaps substantially different, and I believe we should always accommodate such diversity, but there is also a limit to how insistent any of us should be.

  • For example I think your avoidance of versions above V5.2.3 is unnecessary because of backward compatibility, you don’t need to use any of the “improvements” some of which, I think may be helpful to your way of viewing things.
    • At one point I was actively trying to use the new features in a way that may suit you and another diverse user more, simpler and easier to use.
  • I think your continuous insistence on pronouncing this, is harmful to peoples perspective of TiddlyWiki and I am always “biting my lip” when you say this.

That is not clear from the title or the OP. I asked for clarity earlier, and all I got after it is a sense that you are still pursuing what is in the OP. If that’s not the case, then I’m fine. Clarification a little earlier would have been a time saver.

What may seem trivial on the surface isn’t. I’ve seen that kind of thing before, and it causes headaches. Keep the implementation code clean and focused.

It is necessary. I refer to the TW documentation a lot. Maintaining focus and constantly filtering out the things that I don’t want to see and don’t want to use gets exhausting. So I rely on the TW 5.2.3 documentation because it does not have the clutter, and I use TW 5.2.3 because it is a 1 to 1 match with the documentation. That helps me not get distracted, to stay focused. I’m already dealing with sensory and cognitive overload 24x7, so I need to minimize that wherever I can, and so TW 5.2.3 (and no version after it) helps a lot.

I immediately took to TW when I first started because it works the way I think, which helps me tremendously. All new features added after TW 5.2.3, they do not work the way I think, and they frustrate me. So I stick to what works as I think.

If and when I do contribute anything, I do remind folk that I’ve done those things as per TW 5.2.3 in case they might prefer adjusting the contribution with the more current features. Yet another failure at coherent and concise communication, I apologize. It is impossible for me to cognitively keep up with the Joneses, and it gets frustrating. Time for a break.

I had a look at the code but did not test it yet. It looks good. There are 2 things which probably would prevent it from being in the core.

  • I think the name needs to be discussed. because from the description it’s primary function is returning tiddler lists
  • Completely changing the behaviour if a parameter is present or not violates the principle of least surprise.
    • This could also lead to real problems if used like this: [stringlength<variable>]
    • If the variable becomes empty it will return numbers instead of strings and vice versa.
    • hence the problem with the name

As I wrote completely changing the behaviour has a high chance to cause problems.


For filtering title lists I personally would want [titlelength:gt,gteq,eq,lt,lteq[5]] for greater-than, greater-or-equal … Where only 1 operator suffix is possible and “eq” would be the default if there is no suffix.

My question is what would be wrong with [titlelength:gt[5]length[]] to return number, instead of changing the behaviour of stringlength based on the parameters. – As I wrote the name itself needs to be discussed.

just some thoughts

I think there may be other ways to handle this so I am keeping an open mind however I do not personally have a problem with the use of length[] and length[n] because they both relate to length and if not specified length[] finds the length, if specified length[5] filters it based on length.

  • This is a personal preference so I am not proposing it for the core.

There may however be a compromise and I am still researching ideas around extended string handling. I understand the argument against it, and thats fine, however for myself even I find it logical, satisfying and frugal.

  • A compromise may be has.length[] and get.length[] custom operators.
  • Perhaps then has.length[gt],[4] or if one parameter has.length[4] (default to eq)
    • I like you titlelength if it defaulted to eq but its nice to have the opportunity to paramterise the comparison (although not essential)

One issue is to have a native filter operator OR a custom operator because much of this can be done in a macro or procedure, but they need to be evaluated (wikify) which becomes an issue. This is not the case for custom operators or native operators.