Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Getting the shell to evaluate expressions

77 views
Skip to first unread message

Cecil Westerhof

unread,
Jan 6, 2018, 11:44:06 AM1/6/18
to
I want to have the possibility to write things without expr, like:
12 + 34

Based on:
http://wiki.tcl.tk/795

I wrote:
# Save the original one so we can chain to it
rename unknown _original_unknown

# Provide our own implementation
proc unknown args {
puts stderr "WARNING: unknown command: $args"
expr $args
uplevel 1 [list _original_unknown {*}$args]
}

But this results in:
WARNING: unknown command: history event 0
invalid bareword "history"
in expression "history event 0";
should be "$history" or "{history}" or "history(...)" or ...

How could I get it working?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Gerald Lester

unread,
Jan 6, 2018, 12:14:58 PM1/6/18
to
On 01/06/2018 10:29 AM, Cecil Westerhof wrote:
> I want to have the possibility to write things without expr, like:
> 12 + 34
>
> Based on:
> http://wiki.tcl.tk/795
>
> I wrote:
> # Save the original one so we can chain to it
> rename unknown _original_unknown
>
> # Provide our own implementation
> proc unknown args {
> puts stderr "WARNING: unknown command: $args"
> expr $args
> uplevel 1 [list _original_unknown {*}$args]
> }
>
> But this results in:
> WARNING: unknown command: history event 0
> invalid bareword "history"
> in expression "history event 0";
> should be "$history" or "{history}" or "history(...)" or ...
>
> How could I get it working?

Personal recommendation from over 20 years of doing Tcl-- don't!

Embrace how Tcl works and don't try to make it work like XYZ -- that
road leads to a lot of problems in impedance mismatch between what you
think/want it to do and how it really works.

--
+----------------------------------------------------------------------+
| Gerald W. Lester, President, KNG Consulting LLC |
| Email: Gerald...@kng-consulting.net |
+----------------------------------------------------------------------+

Cecil Westerhof

unread,
Jan 6, 2018, 1:59:06 PM1/6/18
to
Gerald Lester <Gerald...@KnG-Consulting.net> writes:

> On 01/06/2018 10:29 AM, Cecil Westerhof wrote:
>> I want to have the possibility to write things without expr, like:
>> 12 + 34
>>
>> Based on:
>> http://wiki.tcl.tk/795
>>
>> I wrote:
>> # Save the original one so we can chain to it
>> rename unknown _original_unknown
>>
>> # Provide our own implementation
>> proc unknown args {
>> puts stderr "WARNING: unknown command: $args"
>> expr $args
>> uplevel 1 [list _original_unknown {*}$args]
>> }
>>
>> But this results in:
>> WARNING: unknown command: history event 0
>> invalid bareword "history"
>> in expression "history event 0";
>> should be "$history" or "{history}" or "history(...)" or ...
>>
>> How could I get it working?
>
> Personal recommendation from over 20 years of doing Tcl-- don't!

Twenty years trumps one month. I would be nice (I was used to it in
ipython), but it is not that important.


> Embrace how Tcl works and don't try to make it work like XYZ -- that
> road leads to a lot of problems in impedance mismatch between what you
> think/want it to do and how it really works.

--

Rich

unread,
Jan 6, 2018, 2:02:08 PM1/6/18
to
Cecil Westerhof <Ce...@decebal.nl> wrote:
> I want to have the possibility to write things without expr, like:
> 12 + 34

Not 100% of your request, but if you want to reduce typing in an
interactive shell, just define an alias:

$ rlwrap tclsh
% interp alias {} e {} expr
e
% e 1 + 2
3

One letter (e, or whatever else you wanted to use) vs. 4.

Brad Lanam

unread,
Jan 6, 2018, 2:19:49 PM1/6/18
to
On Saturday, January 6, 2018 at 11:02:08 AM UTC-8, Rich wrote:
If you don't mind postfix:

% interp alias {} + {} ::tcl::mathop::+
+
% + 1 4
5
%

Rich

unread,
Jan 6, 2018, 2:45:38 PM1/6/18
to
If you prefer postfix, then setting a namespace path allows access to
all the math operators and functions:

$ rlwrap tclsh
% namespace path {::tcl::mathop ::tcl::mathfunc}
% + 1 2
3
% - 8 3
5
% * 5 4
20
% / 12 2
6
% max 1 2 3 5 4
5
% min 4 3 2 5 1
1

Cecil Westerhof

unread,
Jan 6, 2018, 3:14:06 PM1/6/18
to
Rich <ri...@example.invalid> writes:

> Brad Lanam <brad....@gmail.com> wrote:
>> On Saturday, January 6, 2018 at 11:02:08 AM UTC-8, Rich wrote:
>>> Cecil Westerhof <Cecil@> wrote:
>>> > I want to have the possibility to write things without expr, like:
>>> > 12 + 34
>>>
>>> Not 100% of your request, but if you want to reduce typing in an
>>> interactive shell, just define an alias:
>>>
>>> $ rlwrap tclsh
>>> % interp alias {} e {} expr
>>> e
>>> % e 1 + 2
>>> 3
>>>
>>> One letter (e, or whatever else you wanted to use) vs. 4.
>>
>> If you don't mind postfix:
>>
>> % interp alias {} + {} ::tcl::mathop::+
>> +
>> % + 1 4
>> 5
>> %
>
> If you prefer postfix, then setting a namespace path allows access to
> all the math operators and functions:

I do not prefer it, but I do not have a problem with it either. Works
like a charm. Needs to get used to it, but I do not think that that
will be a problem.

Brad Lanam

unread,
Jan 6, 2018, 3:46:11 PM1/6/18
to
On Saturday, January 6, 2018 at 12:14:06 PM UTC-8, Cecil Westerhof wrote:
> Rich <rich@> writes:
>
> > Brad Lanam <> wrote:
> >> On Saturday, January 6, 2018 at 11:02:08 AM UTC-8, Rich wrote:
> >>> Cecil Westerhof <Cecil@> wrote:
> >>> > I want to have the possibility to write things without expr, like:
> >>> > 12 + 34
> >>>
> >>> Not 100% of your request, but if you want to reduce typing in an
> >>> interactive shell, just define an alias:
> >>>
> >>> $ rlwrap tclsh
> >>> % interp alias {} e {} expr
> >>> e
> >>> % e 1 + 2
> >>> 3
> >>>
> >>> One letter (e, or whatever else you wanted to use) vs. 4.
> >>
> >> If you don't mind postfix:
> >>
> >> % interp alias {} + {} ::tcl::mathop::+
> >> +
> >> % + 1 4
> >> 5
> >> %
> >
> > If you prefer postfix, then setting a namespace path allows access to
> > all the math operators and functions:
>
> I do not prefer it, but I do not have a problem with it either. Works
> like a charm. Needs to get used to it, but I do not think that that
> will be a problem.


I should have said "prefix" notation.
And I think Rich copied my incorrect terminology.

The command that Rich mentioned:
> $ rlwrap tclsh
> % namespace path {::tcl::mathop ::tcl::mathfunc}
> % + 1 2

works good. There are more simple examples on the namespace path wiki page.

bll-tecra:bll$ rlwrap tclsh
% namespace path {::tcl::mathop ::tcl::mathfunc}
% max 1 2 3 [+ 4 5] 5
9
%

Rich

unread,
Jan 6, 2018, 3:52:25 PM1/6/18
to
Brad Lanam <brad....@gmail.com> wrote:
> I should have said "prefix" notation.
> And I think Rich copied my incorrect terminology.

Correct you are on that. Didn't even think twice about it (nor notice
the difference).

Christian Gollwitzer

unread,
Jan 6, 2018, 5:28:29 PM1/6/18
to
Am 06.01.18 um 19:49 schrieb Cecil Westerhof:
> Gerald Lester <Gerald...@KnG-Consulting.net> writes:
>
>> On 01/06/2018 10:29 AM, Cecil Westerhof wrote:
>>> I want to have the possibility to write things without expr, like:
>>> 12 + 34

>>> How could I get it working?
>>
>> Personal recommendation from over 20 years of doing Tcl-- don't!
>
> Twenty years trumps one month. I would be nice (I was used to it in
> ipython), but it is not that important.

If you only want this to work on the command line, i.e. not in a script,
then you can use tkcon. It has a "calculator mode". If you switch it on,
it will evaluate expressions first and on failure evaluate Tcl.

Christian

Cecil Westerhof

unread,
Jan 6, 2018, 6:14:07 PM1/6/18
to
Yes, it is only for the command line.

I installed it, but I prefer a terminal above a GUI. And with:
namespace path {::tcl::mathop ::tcl::mathfunc}

I have a reasonable working solution.

Thanks anyway. Maybe I will evaluate it a bit more later on.

Don Porter

unread,
Jan 9, 2018, 2:34:16 PM1/9/18
to
On 01/06/2018 02:19 PM, Brad Lanam wrote:
> % interp alias {} + {} ::tcl::mathop::+
> +

It's very strange to use an alias for that. [namespace path] is a
better tool.

% namespace path tcl::mathop
% + 1 2 3
6


--
| Don Porter Applied and Computational Mathematics Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Brad Lanam

unread,
Jan 9, 2018, 7:18:01 PM1/9/18
to
On Tuesday, January 9, 2018 at 11:34:16 AM UTC-8, Don Porter wrote:
> On 01/06/2018 02:19 PM, Brad Lanam wrote:
> > % interp alias {} + {} ::tcl::mathop::+
> > +
>
> It's very strange to use an alias for that. [namespace path] is a
> better tool.
>
> % namespace path tcl::mathop
> % + 1 2 3
> 6

I'm not familiar with namespace path, and that was the first thing
that came to mind.

Now when I looked at the mathop page and saw how many there were, I
knew there must be some better way.

Fortunately, I have been educated.

Donald Arseneau

unread,
Jan 12, 2018, 11:25:00 PM1/12/18
to
Cecil Westerhof <Ce...@decebal.nl> writes:

> I want to have the possibility to write things without expr, like:
> 12 + 34
>
> Based on:
> http://wiki.tcl.tk/795
>
> I wrote:
> # Save the original one so we can chain to it
> rename unknown _original_unknown
>
> # Provide our own implementation
> proc unknown args {
> puts stderr "WARNING: unknown command: $args"
> expr $args
> uplevel 1 [list _original_unknown {*}$args]
> }
>
> But this results in:
> WARNING: unknown command: history event 0
> invalid bareword "history"
> in expression "history event 0";
> should be "$history" or "{history}" or "history(...)" or ...
>
> How could I get it working?


I'll skip past all the naysayers, noting that nobody seems to
have directly answered the question.

You performed ALL THREE actions on every invalid command:
report error, evaluate expr, execute (original) [unknown].
Obviously you should be selective in which action you attempt.
When you get something that works as an expression, use that,
else report the command error. Remember you will still get
actual command errors passing through!

Try this:

rename unknown _original_unknown

proc unknown args {
if {
[regexp {^\s*(\w+)\s*=\s*(.*)$} [join $args " "] -- _v _e] == 1 && \
[catch {uplevel 1 set $_v "\[expr $_e\]"} _r] == 0
} {
return $_r
} elseif {
[catch {uplevel 1 [list expr [join $args " "]] } _r] == 0
} {
return $_r
} else {
uplevel 1 [list _original_unknown {*}$args]
}
}

% 5-2
3
% x= 5-2
3
% set x
3
% foobar baz
invalid command name "foobar"
%

BUT be warned that this simple hack does not catch all syntactic
variations, AND it has naming collisions between commands, variables,
and math functions.


--
Donald Arseneau as...@triumf.ca
0 new messages