Idea: Enhance the length operator

I understand your concerns in general but have not seen a good argument. The is no multipurpose here. It would have one purpose, handling lengths.

So if I make my own stringlength operator unless someone can present a better argument I will combine these features.

This thread is no longer about the enhancement-idea in the OP, right ?

What in blazes is this discussion now about ?

Very confusing.

You’re right that we haven’t been putting forth many arguments; mostly it’s been, Our long experience—combined with programming folk wisdom—says this is a bad idea. Although to be fair, I did supply a link to my blog post which does present a real argument. and the video by Rich Hickey, Simple Made Easy provides a long form explanation of the more general problem.

Nobody will bother complaining… unless you propose such an operator be pushed to the core.

One argument against this style, though, if you want to hear it, goes like this:

Ok, this operator handles length. That’s great if I want to count the items in a collection or filter to include all those that have exactly eight items.

But what if I want to know about the length property of an input tiddler with Rectangle properties? Shouldn’t it take this tiddler’s fields into account? What if I want to collect the length in centimeters of the rendered text in a given font? Should it then be optionally written [<input>length:Helvetica:14pt:cm[]]? What if the input is a tiddler title? Can’t we get the length of its text field? Or do we want to handle any arbitrary field? So perhaps we can have a field suffix, no? And while those sound far-fetched, perhaps, this one seems much more likely: length:gt[5]. I could keep going, giving all sorts of ways length might be interpreted.

So how is a reader of your wikitext (which might be you in a few months) going to keep track of all the ways this function can be used?

The answer of course is to pare back the number of different ways your function can be interpreted. And then do so again, and again. When do we stop? Antoine de Saint-Exupéry has the answer:

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.

This should lead inexorably to supporting a single behavior.

There is more concern, at least on my part, about consistency in the way a function (procedure/operator/macro) returns than in what it accepts for input… When reading code or markup, It’s much harder to understand what something does if I can’t comfortably know that it returns, say, a number.

2 Likes

: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.