[TW5] plugin update: tobibeer/setvars => NEW: conditionals

292 views
Skip to first unread message

Tobias Beer

unread,
Dec 18, 2015, 7:39:22 PM12/18/15
to tiddl...@googlegroups.com
Hi everyone,

Ok, I did some more testing and realized that
there is no need for a full ternary-style expression doing if ? then : else.

So, instead of doing...

if ( true ? then : else)

You'll simply do...

if (true ? then) || else

I'll push an update soon.

Best wishes,

Tobias.

Alex Hough

unread,
Dec 19, 2015, 4:09:30 AM12/19/15
to tiddl...@googlegroups.com
Hi Tobias,

What kind of uses could this development be put to?

Alex

On Saturday, 19 December 2015, Tobias Beer <beert...@gmail.com> wrote:
Hi everyone,

I took a few hours to create a new version 0.5.5 of tobibeer/setvars.

Get the update from here:


This allows the setvars widget to declare variables leveraging basic conditionals using either of...
  • OR logic
    this || that || another » takes the first value that is non-empty and then stops
  • IF clauses
    IF( condition ? then-value : else-value ) » the condition is interpreted as true if it evaluates to non-empty
    » you can use OR logic within any of the IF clause statements
Best wishes,

Tobias.

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.
To view this discussion on the web visit https://groups.google.com/d/msgid/tiddlywiki/01394670-dcf8-4700-85d6-f3300f9dcfc7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tobias Beer

unread,
Dec 19, 2015, 7:06:57 AM12/19/15
to tiddl...@googlegroups.com
Hi Alex,
 
What kind of uses could this development be put to?

I am sure those will emerge with people starting to use setvars.
If you create an interesting use-case, please always post it here,
so people actually now what to make of all this.

For example, I often find myself having to create two reveals,
one for each condition, just because some string
may have two states, e.g. "emtpy" or "non-empty".

With the conditionals in setvars, I simply, dynamically compute the variable upfront
and then only use one reveal to create the output I desire.
In fact, I may not even need a reveal after all!
So, no need to also define superfluous states
or complicated type="match/nomatch" conditions,
that often behave in unexpected ways.

Best wishes,

Tobias.

Tobias Beer

unread,
Dec 19, 2015, 7:23:05 AM12/19/15
to tiddl...@googlegroups.com
Hi again, Alex,

As for replacing reveals, there is something about setvars I have not yet communicated:

Other than most widgets in the core,
there are cases where setvars only computes its variables once,
and that is by design!

Try this in a new tiddler on: http://tobibeer.github.io/tw5-plugins

setvars
: <$setvars uuid="[id]" _id="[make[%uuid%]]"><<uuid>></$setvars>
; set
: <$set name="uuid" filter="[make[%uuid%]]"><<uuid>></$set>

Now, go ahead and switch a tab in the sidebar.
Observe what happens to the output of the uuid variable in both cases!

Obviously, if you were to want to replace reveals with setvars,
you will need to make sure that you use constituent attributes that will refresh.

So, if you use a text-reference or variable-attribute for a computed variable
then the widget should refresh, should these attribute values change,
in other words, should the text-references or wikitext-variable contents change.

Best wishes,

Tobias.

AlexHough

unread,
Dec 19, 2015, 9:48:04 AM12/19/15
to TiddlyWiki
Tobias,

I was thinking about a use case, it follows on a was of thinking using the conceptual metaphor "TW as a synthesiser" and influenced by a few things I've come across recently

First the "inputs" ...


Treat the recording studio as a laboratory for conceptual thinking — rather than as a mere tool.— Brian Eno [1]
* also Eno's oblique strategies

Tensor - deep learning, inference [2]
* the idea of training a computer

Self-similarity, generative hypertext systems [3]

Luhman, zettelkasten [4]
* German social systems thinker saw his zettelkasten as a collaborator

Margert Boden [5] talks about machine creativity


Outputs

Data from TW could be presented back to the user, he/ she could use it creatively to trigger Enoesque oblique strategies such as "Treat the TiddlyWiki studio as a laboratory for conceptual thinking — rather than as a mere tool" -- see what I did there? Cloned Eno's quote and claimed it for myself.

In terms of a human machine learning learning or creativity system (me and my TiddlyWiki), I want to put something into the system which generates some chance of serendipitous discovery. Luhman held strong views on how a zettlekasten see [4.1] - he didn't want things over categorised....

TiddlyWiki can become highly absorbing, but sometimes I will start wanting to write about the connections between, for example, modularity, recursion and pattern languages, but then end up spending hours and hours making a button that glows like one on a vintage synth. If only I could train TW to interrupt me and steer me in the "right direction". Like a good human collaborator, I would respect the interruption. I'd then me encouraged to reflect on my approach, and also give some feedback to my collaborator... "thanks for that, but next time could you leave it a little longer? I really thinK that having a pulsing red "is dirty" button would be a milestone on the critical path here...."

Setvars and eval

The idea could involve setvars and eval... what follows is largely dependant on my understanding of what setvars and eval could do.

10) compare two "created fields" - set a variable
20) take one away from another - eval
30) if the result of eval is X, then make the TW do something, otherwise do something else


The "conversation" could go a bit like this

"You are creating a lot of stylesheet tiddlers in the last 30 mins. At the start of this session you created a tiddler entitled "Generative hypertext" with links to "Self-similarity", "Recursion" and "Quine", and these links are still missing. Maybe you'd like to open these now?"

Basically we have build in oblique strategies in a generative hypertext implimentation



best wishes



Alex

[3]  ‏@Jermolene Dec 13: "Most personal organisation tools aren’t generative; you can’t make anything new out of the things you collect"
[4] Luhman, zettelkasten


Tobias Beer

unread,
Dec 19, 2015, 10:02:06 AM12/19/15
to TiddlyWiki
Hi Alex,

Curious to see what you will come up with.
Allow me to focus on the plugins...

Setvars and eval

The idea could involve setvars and eval... what follows is largely dependant on my understanding of what setvars and eval could do.

10) compare two "created fields" - set a variable
20) take one away from another - eval
30) if the result of eval is X, then make the TW do something, otherwise do something else

Can do each of those with either of those plugins.

Best wishes,

Tobias. 

Tobias Beer

unread,
Dec 19, 2015, 5:46:26 PM12/19/15
to TiddlyWiki
Hi everyone,

I just published version 0.5.6 of tobibeer/setvars:
  • simplified conditionals:
    • if(condition?then) || else
    • much simpler code than for ternary operator as below
  • no more ternary style clauses:
    • if(condition?then:else)
    • so these are not supported anymore
Get it from here:

Tobias Beer

unread,
Dec 20, 2015, 5:30:43 AM12/20/15
to TiddlyWiki
Went jogging this morning and came back with another nice idea.

you can refer to variables previously declared in the same setvars widget instance.

Get the update from the usual place:


Here's a macro that shows how that works:

This macro routes a link to tiddlywiki.com should there not be a local tiddler by that name while also allowing you to use a pretty title:


\define route(title,pretty)
<$setvars
_exists="[[$title$]is[tiddler]]"
_not="[[$title$]!is[tiddler]]"
title="if( \$pretty$\ ? \$pretty$\ ) || \$title$\"
link="
if( [exists] ? \[[\title\|$title$]]\ ) ||
if( [not] ? \[ext[\title\|http://tiddlywiki.com#$title$]]\ )">
<<link>>
</$setvars>
\end


Note: Notice how the link variable refers to the title variable declared before it!

<<route TextReferences "text-reference">>

text-reference

Best wishes,

Tobias.

Alex Hough

unread,
Dec 20, 2015, 5:51:16 AM12/20/15
to TiddlyWiki
Hi Tobias,

I've been playing with eval, and I have the basics up and working.

As an exercise  I am aiming to work out how much it would cost get all your calories from a particularly cheep bag of chapati flour (£3 for 10kg!): I 

I can create tiddler fields and eval them, but how would I store an eval in a tiddler field? 
Then, in another eval, I would calculate the cost of meeting the calorie requirement with the flour. My thinking is that it would be good to store evals in fields along with data used to calculate that eval

Should I be trying to do this, or is there a better way?

Here is the contents of a tiddler I created on your plugin site:



Total energy required: <$edit-text tiddler="Carbo-needs" field="kcalDay"tag="input" placeholder="enter energy kcal per day" default="2,500"/>

Percent from carb: <$edit-text tiddler="Carbo-needs" field="Carbo-percent"tag="input" placeholder="percent" default="45"/>

----
```
<$set name="CostPerKilo" filter="[[]eval[{{Carbo-needs!!kcalDay}}*{{Carbo-needs!!Carbo-percent}}]]">
cals from carbs = <<CostPerKilo>> kcal
</$set>
```
<<<
<$set name="CalsFromCarbs" filter="[[]eval[{{Carbo-needs!!kcalDay}}*{{Carbo-needs!!Carbo-percent}}]]">
cals from carbs = <<CalsFromCarbs>> kcal
</$set>
<<<


How to write CalsFromCarbs variable to a tiddler field


Alex

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.

Tobias Beer

unread,
Dec 20, 2015, 6:38:14 AM12/20/15
to tiddl...@googlegroups.com
Hi Alex,

How to write CalsFromCarbs variable to a tiddler field

This is not exactly the eval thread, plus your barrier is actually not even about eval. ;-)
Perhaps you thought setval would help with it,
but in this matter you need to do exactly what you'd do with set or vars.

Before you read up on the solution, be careful with tiddler fields!
TiddlyWiki always turns them into lowercase,
so kcalDay and Carbo-percent will never be fields if you enter them in edit-mode,
which means your eval calculations will fail, because there are no such fields!

However, I am not sure if and why TiddlyWiki would be forcing this behaviour.

@Jeremy, When and Why are we forcing field-names to be lowercase?

Also, if we are forcing fields to be all-lowercase,
then tiddler.getFieldsString must always turn a requested field to lowercase first! => ticket?

Now to the quite simple solution: use a ButtonWidget like so...

<$set name="CalsFromCarbs" filter="[[]eval[{{Carbo-needs!!kcal-per-day}}*{{Carbo-needs!!carbo-percent}}/100]]">
<$button set="!!kcal-carbs" setTo=<<CalsFromCarbs>>>
set ''kcal-carbs'' to <<CalsFromCarbs>>
</$button>
</$set>

; kcal-carbs
: {{!!kcal-carbs}}

Best wishes,

Tobias.

Tobias Beer

unread,
Dec 20, 2015, 6:54:55 AM12/20/15
to TiddlyWiki
Hi, again, Alex,
 
Now to the quite simple solution: use a ButtonWidget like so...

Actually, there is a perhaps more sensible solution where you don't store that computed result into a field at all, but rather store the formula for it in that field using the eval widget, e.g.:

title: Carbo-needs
kcal
-per-day: 2500
carbs
-percent: 45
kcal
-carbs: <$eval>{{Carbo-needs!!kcal-per-day}}*{{Carbo-needs!!carbs-percent}}/100</$eval>

And then, in any tiddler, do...

{{Carbo-needs!!kcal-carbs}}

Best wishes,

Tobias.

Alex Hough

unread,
Dec 20, 2015, 9:50:05 AM12/20/15
to TiddlyWiki
Hi Tobias,

first, thanks for taking time to respond.

I think the latter solution is better, it brings forth a good feeling. Storing the eval in a field makes sense, its similar to the cubed example;
<$list filter="[[]eval{eval-Examples!!cubed}]"/>

I like the way mathematical functions are presented as "filters"

Do you think it would be worth creating a calcs tiddler with common calcs, such as squared, percent?


Alex

--
You received this message because you are subscribed to the Google Groups "TiddlyWiki" group.
To unsubscribe from this group and stop receiving emails from it, send an email to tiddlywiki+...@googlegroups.com.
To post to this group, send email to tiddl...@googlegroups.com.
Visit this group at https://groups.google.com/group/tiddlywiki.

Matabele

unread,
Dec 20, 2015, 10:47:45 AM12/20/15
to TiddlyWiki
Hi 

I have been considering an rpn[] filter operator (reverse polish), which treats the operand as a stack (if missing - take the current list as a stack.) Once implemented, options could be added for any calculation possible on an HP calculator e.g:

rpn:+[] -- pop the last two item off the stack, add them, and push the result back to the stack
rpn:sin[] -- pop the last item off the stack, take the sine, and push the result back to the stack

Thoughts?

regards

On Sunday, 20 December 2015 16:50:05 UTC+2, AlexHough wrote

Matabele

unread,
Dec 20, 2015, 11:02:17 AM12/20/15
to TiddlyWiki
Hi Tobias

Much nicer syntax -- declare all your variables first -- then use them in your calculations \o/

regards

Tobias Beer

unread,
Dec 20, 2015, 11:41:12 AM12/20/15
to TiddlyWiki
Hi Alex,
 
Do you think it would be worth creating a calcs tiddler with common calcs, such as squared, percent?

I think it would make sense to have topic-specific tiddlers wherever those computed values are necessary. So, I don't think I'd want a generic "calcs" tiddler, or know what to put in it and why.

1) Perhaps you'd rather want macros using the eval widget, but calculating simple or sophisticated things in a parametric manner, e.g.:

\define ++(val) <$eval>{{$val$}}+1</$eval>

<<++ !!myfield>>

2) Also, what works quite well, and I didn't know it would, is to further calculate with a field containing a computation.

So, let's say we take your field from the last example:

kcal-carbs: <$eval>{{Carbo-needs!!kcal-per-day}}*{{Carbo-needs!!carbs-percent}}/100</$eval>

You can simply keep calculating with it:

<$eval>{{Carbo-needs!!kcal-carbs}}*2</$eval>

3) A third method would be to use templates, e.g.

title: $://total-price

<$eval>({{!!price}} + {{!!shipping}}) * (1+{{$:/finance/tax-rates!!vat}}/100)</$eval>

And then:

title: Basket

total
: {{||$://total-price}}

So, there's three ways to leverage the eval widget.
  1. macros
  2. fields containing the widget
  3. templates
Best wishes,

Tobias.

Tobias Beer

unread,
Dec 20, 2015, 11:43:44 AM12/20/15
to tiddl...@googlegroups.com
Hi Matabele,
 
Much nicer syntax -- declare all your variables first -- then use them in your calculations \o/

I agree, especially with any complex definitions. It's not actually necessary, but it feels more natural to first declare the parameter attributes you want to use later and only then specify the variables that use these values to achieve a final result.

Best wishes,

Tobias.

PMario

unread,
Dec 29, 2015, 4:14:52 AM12/29/15
to TiddlyWiki
On Sunday, December 20, 2015 at 12:38:14 PM UTC+1, Tobias Beer wrote:
@Jeremy, When and Why are we forcing field-names to be lowercase?

see details at: https://github.com/Jermolene/TiddlyWiki5/issues/2155
 - https://github.com/Jermolene/TiddlyWiki5/issues/2155#issuecomment-167578296
 - https://github.com/Jermolene/TiddlyWiki5/issues/2155#issuecomment-167590321

It's an implementation detail, as Jeremy shows here: https://youtu.be/FDV5ojcCLB8?t=1253

It is possible to change, and it may change in the future, but imo it won't be an easy change. So we shouldn't expect it in the near future.

 
Also, if we are forcing fields to be all-lowercase,
then tiddler.getFieldsString must always turn a requested field to lowercase first! => ticket?

If you request a change in the TW core API, I think, you should raise a new ticket. ... since the above one is a "question ticket"

-mario

Matabele

unread,
Dec 29, 2015, 4:42:38 AM12/29/15
to tiddl...@googlegroups.com
Hi


On Tuesday, 29 December 2015 11:14:52 UTC+2, PMario wrote:
 
Also, if we are forcing fields to be all-lowercase,
then tiddler.getFieldsString must always turn a requested field to lowercase first! => ticket?

Perhaps a better tactic would be to force lowercase upon creation (they are enforced upon a save/refresh):
 -- the $fieldmangler widget does this already with this statement:
var trimmedName = name.toLowerCase().trim();
-- the $action-setfield widget does not contain any equivalent
-- neither does the $navigator widget when handling a "tm-new-tiddler" message

Perhaps another utility function is needed to process field names upon creation (which may then be called from these widgets)
-- enforce lowercase and trim `var trimmedName = name.toLowerCase().trim();`
-- check for valid name `$tw.utils.isValidFieldName(trimmedName)`
-- (the isValidFieldName() function, currently converts to lower case before testing -- therefore returning a valid response for an invalid name)
-- and return a valid name or fail

regards

Tobias Beer

unread,
Dec 29, 2015, 4:54:12 AM12/29/15
to TiddlyWiki
Hi Mario,
 
If you request a change in the TW core API, I think, you should raise a new ticket. ... since the above one is a "question ticket"

Sure. For now, the safest bet appears to be to always ask for lowercase field-names, period.

Being allowed to use camelcase for field-names, if only for readability, should be an option, imho.

Using field-names to refer to tiddler titles is simply not an option. The one way to do that would be to use indexes in a data tiddler, provided the key does not contain a colon. On the other hand, perhaps data tiddlers may need a way to escape an index so that it can contain a colon, after all, e.g.

[[$:/Some/System/Tiddler-With-A-Colon]]: the value for it

Best wishes,

Tobias. 

Matabele

unread,
Dec 29, 2015, 6:11:55 AM12/29/15
to TiddlyWiki
Hi

Perhaps a new utility function that can be called everywhere a field gets created -- along the lines of this:

exports.addField = function(tiddler,name,value) {
 
var trimmedName = name.toLowerCase().trim();
 
if(!$tw.utils.isValidFieldName(trimmedName)) {
 
if(!hadInvalidFieldName) {
 alert
($tw.language.getString(
 
"InvalidFieldName",
 
{variables:
 
{fieldName: trimmedName}
 
}
 
));
 hadInvalidFieldName
= true;
 
return;
 
}
 
} else {
 
if(!value && tiddler) {
 value
= tiddler.fields[trimmedName];
 
}
 addition
[trimmedName] = value || "";
 
}
 
return;
};

regards


On Tuesday, 29 December 2015 11:14:52 UTC+2, PMario wrote:
Reply all
Reply to author
Forward
0 new messages