Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional math operator equal[] #3781

Closed
AnthonyMuscio opened this issue Feb 20, 2019 · 17 comments
Closed

Additional math operator equal[] #3781

AnthonyMuscio opened this issue Feb 20, 2019 · 17 comments

Comments

@AnthonyMuscio
Copy link
Contributor

AnthonyMuscio commented Feb 20, 2019

Is there already a way in the maths operators proposed that allows us to test a simple value?
[minor edits done]

I think this is not only essential but it would simplify a lot for users, and support the other maths operators.

  • Currently we can say prefix[3]suffix[3] to test if the result is 3
  • I would like to propose an equal[3] in addition to the above.
  • However since this should be able to test strings of any kind perhaps a broader name could be used.

If it were possible is[3] or is[yes] would be great for unreserved names defined in https://tiddlywiki.com/#is%20Operator

One method to separate from the normal is operation would be
is:value[anumber] and if it contains a non matching or non number no result is returned, 0 is valid blank is not. This could also be used to test the value is a number for input testing.

is:string[anumberorstring] and if it contains matching any thing the value is returned

Of course we would hope

  • !is:value[3] AND !is:string[string2] would work
  • as should +[is:value[4]]

I currently have the following working in pre-release. It tests a tiddler title matches a w3w.co geolocation address.

filter="[<currentTiddler>>prefix[///]!prefix[.]!suffix[.]split[.]count[]prefix[3]suffix[3]]"
but
filter="[<currentTiddler>>prefix[///]!prefix[.]!suffix[.]split[.]count[]is:value[3]]"
or
filter="[<currentTiddler>>prefix[///]!prefix[.]!suffix[.]split[.]count[]equal[3]]"
Would be better

I also see a range of novel uses with the else ~ and title, which resembles a CASE or parse statement
filter="<n> [is:value[2]title[two]] ~[is:value[2]title[two]] ~[is:value[3]title[three]]"

filter="<n>[is:value[2]lookup[$:/number/]] ~[is:value[2]lookup[$:/number/]] ~[is:value[3]lookup[$:/number/]]"

@Jermolene
Copy link
Member

Hi @AnthonyMuscio there's some existing discussion on this in #2253

I do intend to add the full set of comparison operators. We need to figure out:

  • How to distinguish string semantics vs. numeric semantics. In the case of string semtantics we probably want to permit the option of a case insensitive comparison
  • How to represent the result of a comparison (e.g. as "yes"|"no" or as a non-empty vs. empty value

@AnthonyMuscio
Copy link
Contributor Author

Thanks for the reference to the earlier discussion

Not with sanding there may be issues therein, the environment has changed since that was raised. With the maths operators foreshadowed and other enhancements to the Filter Operators since the original request.

As in my example I would favour non-empty vs. empty value because it allows the use of ~[[else]] , if it was yes or no true or false,. you then need to code the next step, how to respond to the result.

Case may be handled by

  • is:upper[value]
  • is:lower[value]

AND a useful one

  • is:camel[value]

Actually is:parm[value] implies empty value or not give the way filters work. Perhaps my proposed "is" operator extensions could be provided alongside equals[] or value[] as proposed which meets the requirements of the other issue a bit closer. I think value[] is best if it is numbers and strings, but people will be looking for "equals".

@AnthonyMuscio
Copy link
Contributor Author

Even is:sentence ?

And one asks do we have a filter to make a title/value upper/lower/sentence

We could use such an operator to ignore case by converting to lower before testing rather than build in a case sensitive option. If relevant build case insensitivity into the filter logic not into an operator makes it more reusable.

Regards
Tony

text:loweris[lowecasetest]

@Jermolene
Copy link
Member

Hi @AnthonyMuscio I don't think we can really overload the "is" operator like that. Think about how complicated it would make the documentation.

@BurningTreeC
Copy link
Contributor

Hi @AnthonyMuscio @Jermolene

PR #3760 is an attempt on an equals[] and !equals[] filter but it's numeric only

@pmario
Copy link
Member

pmario commented Feb 20, 2019

The reveal-widget is able to compare values: https://tiddlywiki.com/#RevealWidget

@AnthonyMuscio
Copy link
Contributor Author

The reveal-widget is able to compare values: https://tiddlywiki.com/#RevealWidget

Mario,

I looked, can it compare variables? I so often have values in variables by reveal seems to need state tiddlers or text references at best. Is this a missing feature?
Regards
Tony

@AnthonyMuscio
Copy link
Contributor Author

AnthonyMuscio commented Feb 20, 2019

Hi @AnthonyMuscio I don't think we can really overload the "is" operator like that. Think about how complicated it would make the documentation.

To be clear I am looking for the functionality, not the specific adoption of the above suggestions.

I think I could easily make the documentation legible. But I do not know about other "overload" issues. a key fact is it would approach everyday English and be easier to understand. Is resembles an "if" only "is" implies exist or not. so is:upper

Would it be too bold to introduce the if:test[value] operator on this?

"[!is[system]!if[tiddlername]]" vs "[!is[system]] -[[tiddlername]]"

"[!is[system]if:upper[]]"
"[!is[system]if:number[]]" tiddlers who's title is a valid number
" +[if]"

The Thing "is" the is operator. for me at least is not that used beyond [!is[system]] and is:parm[value] is a substantially different form and will be used to test numbers and strings "is:foo[bar]" vs "is[tiddlertype]"

It also follows the
fieldname[fieldnamevalue] form for types and value type

Regards
Tony

@pmario
Copy link
Member

pmario commented Feb 21, 2019

"[!is[system]if:number[]]" tiddlers who's title is a valid number

What are valid numbers for you? eg: 0x11, 0b11, 0o11 are valid numbers

@AnthonyMuscio
Copy link
Contributor Author

AnthonyMuscio commented Feb 21, 2019

Mario,

If I look at the current proposed maths operators simple integer +- and floating point with limited precision would be enough. After all this will be what 98% of users will require.

0-9 . - + may be enough

Calc, evans formulae and other maths plugins should cover the rest of the requirements.

This is all I have seen so far

negate - negation
abs - absolute value
ceil - smallest integer greater than or equal to a given number
floor - the largest integer less than or equal to a given number
round - the value of a number rounded to the nearest integer
trunc - the integer part of a number by removing any fractional digits
sign - the sign of a number, indicating whether the number is positive, negative or zero
add - add an operand to every number in the input list
subtract - subtract an operand from every number in the input list
multiply - multiply every number in the input list by an operand
divide - divide every number in the input list by an operand
remainder - replace each item in the input list with the remainder when dividing that number by an operand
max - replace any number in the input list larger than the operand with the operand
min - replace any number in the input list smaller than the operand with the operand
fixed - formats a number using fixed-point notation with the number of fractional digits after the decimal point given by the operand
precision - returns a string representing the number to the precision specified in the operand
exponential - returns a string representing the Number object in exponential notation with the number of digits after the decimal point specified in the operand
sum - replaces the input list with the sum of all the entries
product - replaces the input list with the product of all the entries
maxall - replaces the input list with the maximum value of all the entries
minall - replaces the input list with the minimum value of all the entries
length - replaces each item in the input list with its string length in characters
uppercase - replaces each item in the input with its uppercase equivalent
lowercase - replaces each item in the input with its lowercase equivalent
trim - trims each item in the input list
concat - concatenates all of the items in the input list into a single string
split - splits each of the items in the input list by a given separator
join - joins all of the items in the input list with a given separator

Regards
Tony

@AnthonyMuscio
Copy link
Contributor Author

PS I am looking forward to play with

ceil - smallest integer greater than or equal to a given number
floor - the largest integer less than or equal to a given number

@pmario
Copy link
Member

pmario commented Feb 21, 2019

Form my point of view this is clearly plugin territory. Doing some simple math is easy. ... but as soon as you start to calculate with money, the trouble starts. ... It needs to be precise!!!

eg:

  • open your dev-console F12
  • select the console tab
  • type: 0.1 + 0.2 and have fun with the result: 0.30000000000000004
    • which is definitely wrong for every accountant that you'll ever meet.
  • the problem here is the float type.

I think. If I want to have statistic functions in the core, it has to be right. Otherwise we will only have trouble.

@AnthonyMuscio
Copy link
Contributor Author

AnthonyMuscio commented Mar 18, 2019

I would still like an equals test operator but given the aforementioned issues I will leave it to others to address the broader use cases.

What about titleis[string] a selection modifier, not a constructor? so we can then have !titleis[string] and [titleis<name>] or [titleis{!!fieldname}] [titleis{tiddlername}]

I have found an acceptable method when testing fields, but not titles in a filter.

<$list filter="[all[current]test-field[yes]]" emptyMessage="not yes message">
     "[test-field[yes]]" in <<currentTiddler>>
</$list>

<$list filter="[all[current]test-field[no]]" emptyMessage="not no message">
     "[test-field[no]]" in <<currentTiddler>>
</$list>

But given the above since, testing the fields in the current tiddler is common

Could we collapse [all[current]test-field[yes]] into [test-field:here[yes]] ?

Another example for the record

<$list filter="[is[current]field:test-field[yes]]" emptyMessage="not yes message">
     "[test-field[yes]]" in <<currentTiddler>>
</$list>

@AnthonyMuscio
Copy link
Contributor Author

Form my point of view this is clearly plugin territory.
Not if it is it only doing a string comparison, my key use case.

* type: `0.1 + 0.2` and have fun with the result: `0.30000000000000004`

This result is an artefact of the calculation, and need not have anything to do with a comparison. If the proposed change to the $view widget was done we could say <$view value=<> format="0.00"> then "[equals[0.30]]"

Regards
Tony

@AnthonyMuscio
Copy link
Contributor Author

AnthonyMuscio commented Mar 23, 2019

Mario,

Form my point of view this is clearly plugin territory.

Not if it is it only doing a string comparison, my key use case.

* type: `0.1 + 0.2` and have fun with the result: `0.30000000000000004`

This result is an artefact of the calculation, and need not have anything to do with a comparison. If the proposed change to the $view widget was done we could say <$view value=<> format="0.00"> then "[equals[0.30]]"

This is why I originally suggested is[value]

Regards
Tony

@Jermolene
Copy link
Member

This was fixed with #4554

@AnthonyMuscio
Copy link
Contributor Author

Thanks Jeremy, Lovely work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants