If I want to introduce some new expression operator, e.g. "%%" to deal with some custom data structure, I will need to re-define "expr" command to recognize it. Is this right?
Basically TCL extension is at the command level, there is no interface to directly add new operator.
Could you confirm my understanding?
The operators in Tcl are implemented directly in Tcl's bytecode engine; you can't extend them or modify their semantics. Not without editing the expression parser (written in C) or the bytecode engine itself (a compiler and an execution engine, both written in C). Extending this part of Tcl directly is rather difficult. (You're looking at tclParseExpr.c, tclCompExpr.c and tclExecute.c at least to make things work, and quite possibly the other tclParse* and tclComp* files too, as well as the assembler and maybe the disassembler. Not to be taken on lightly!)
However…
You can write your own command that interprets a string as anything you want, including an expression involving whatever new operators you desire. This is what VecTcl does. Under the covers, it converts its expression language into calls to Tcl commands that implement the various operators (some of which are implemented in C, but as a normal extension package, so that's nothing unusual).
Effectively, it converts an invoke of one of its expressions:
vexpr {3*x}
into something a bit like this:
numarray::* 3 [set x]
which it then can execute using Tcl's bytecode engine (frankly, a trivial execution, but it makes more sense in more complex examples; see the VecTcl tutorial, which is a bit too long to reproduce here).
The mathop manual page calls out explicitly that while you can access the expr operators using the ::tcl::mathop namespace you cannot add new ones nor redefine the existing ones there. You can add you expr functions using the tcl::mathfunc namespace as documented in the expr man page so if a function will do that is the simplest method to do what you want.
Otherwise you could intercept the expr command itself. If you rename the expr command and define your own replacement you can do some expression parsing and replace your custom operator with a function call or pass the expression on to the real implementation. Below is a trivial example.
rename expr _expr
proc expr {args} {puts "called expr $args"; _expr {*}$args}
In short, your understanding is correct. You cannot inject new operators into the expr expression parser.
Related
Python has such methods as __add__, __mul__, __cmp__ and so on (called magic methods), which are used as a class methods and can give a different meaning to adding(+), multiplying(*), comparing(==), ... two instances of a class. My question is do other languages have a similar method? I'm familiar with Java, C++, ruby and PHP, but never came across such a thing. I know all four have a constructor method which corresponds to __init__, but what about other magic methods?
I tried googling "Magic methods in other programming languages" but nothing related showed up, probably they got different names on different languages.
In general, having too much "magic" in a language is a sign of bad language design. Maybe that is why there are not many languages which have magic methods?
Magic like this creates a two-class system: the language designer can add new magic methods to the language, but the programmer is restricted to only use the methods that the High Priest Of Language Design allows them to. In general, it should be possible for the programmer to do as much possible without requiring to change the language specification.
For example, in Scala, +, -, *, /, ==, !=, <, >, <=, >=, ::, |, &, ||, &&, **, ^, +=, -=, *=, /=, and so on and so forth, are simply legal identifiers. So, if you want to implement your own version of multiplication for your own objects, you just write a method named *. This is just a boring old standard method, there is absolutely nothing "magic" about it.
Conversely, any method can be called using operator notation, i.e. without a dot. And any method that takes exactly one argument can be called without parentheses in operator notation.
This does not only apply to methods. Also, any type constructor with exactly two type arguments can be used in infix notation, so if I have
class ↔️[A, B]
I can do
class Foo extends (String ↔️ Int)
which is the same as
class Foo extends ↔️[String, Int]
Well … I kinda lied: there is some syntactic sugar in Scala:
foo() is translated to foo.apply() if there is no method named foo in scope. This allows you to effectively overload the function call operator.
foo.bar = baz is translated to foo.bar_=(baz). This allows you to effectively overload property assignment. (This is how you write setters in Scala.)
foo(bar) = baz is translated to foo.update(bar, baz). This allows you to effectively overload index assignment. (This is how you write array or dictionary access in Scala, for example).
!foo (and a couple of others) are translated to foo.unary_!.
foo += bar will try to call the += method of foo, i.e. it is equivalent to foo.+=(bar). But if this fails and foo is a valid lvalue, and foo has a method named +, then Scala will also try foo = foo + bar instead.
Also, precedence, associativity, and fixity are fixed in Scala: they are determined by the first character of the method name. I.e. all methods starting with * have the same precedence, all methods starting with - have the same precedence, and so on.
Haskell goes a step further: there is no fundamental difference between functions and operators. Every function can be used in function call notation and in operator notation. The only difference is lexical: if the function name consists of operator characters, then when I want to use it in function call notation, I have to wrap it in parentheses. OTOH, if the function name consists of alphanumeric characters and I want to use it in operator notation, I need to wrap it in backticks. So, the following are equivalent:
a + b
(+) a b
a `plus` b
plus a b
For operator usage of functions, you can freely define the fixity, associativity, and precedence, e.g.:
infixr 15 <!==!>
In Ruby, there is a pre-defined set of operators that has corresponding methods, e.g.:
def +(other)
plus(other)
end
In C++ operator overloading is what your are looking for.
Java has no native support for operator overloading (Reference).
C has no operator overloading (Reference). Thus, a lot of add, mult and so on functions are written. Often those are macros, because then they can be used for different types. IMHO this is why I like C++ better.
#Alex gave reference to a nice overview of operator overlaoding.
I'm trying to pass a function to a method and then pass parameters to the method I passed when calling it, but if I pass more than one parameter then the method fails with an error:
function debugMeStuffs($someBlah, $somePoo) {
Write-Host $someBlah
Write-Host $somePoo
}
function invokeOnHosts ([scriptblock]$funcToCall, $param1, $param2, $startRange, $endRange) {
#Param($funcToCall)
$i = $startRange
for($i = [int]$startRange; $i -le $endRange; $i++) {
# HOW DO I MAKE THIS WORK WITH MULTIPLE PARAMETERS?!?!?!?
$funcToCall.Invoke('blah' 'poo')
}
}
invokeOnHosts $function:debugMeStuffs "param1" "param2" 4 7
Things I've tried:
$funcToCall("blah" "poo")
$funcToCall('blah' 'poo')
$funcToCall.Invoke("blah" "poo")
$funcToCall.Invoke('blah' 'poo')
$funcToCall 'blah' 'poo'
$funcToCall.Invoke 'blah' 'poo'
$funcToCall "blah" "poo"
$funcToCall.Invoke "blah" "poo"
None of the above seem to work. Is there something else I need to do to make this work?
.Invoke() is a .NET method, so the usual method-call syntax applies: you need
parentheses - (...) - around the list of arguments
you must separate the arguments with ,
$funcToCall.Invoke('blah', 'poo')
This contrasts with PowerShell's own syntax for calling cmdlets and functions, which is shell-like[1]:
no (...) around the argument list
arguments must be separated with spaces.
& $funcToCall blah poo # equivalent of the method call above.
A command such as the above is parsed in argument mode, which is why quoting the arguments in this simple case is optional.
Note the need for &, PowerShell's call operator, which is needed to execute the script block stored in $funcToCall; this is generally necessary for invoking a command stored in a variable, and also for command names / paths that are quoted.
Given that it's easy to get confused between PowerShell's command syntax and .NET's method syntax, it's best to stick with PowerShell-native features[2], if possible.
That said, being able to call methods on .NET types directly is a wonderful extensibility option.
To help avoid accidental use of method syntax when calling PowerShell commands, you can use Set-StrictMode -Version 2 or higher, but note that that entails additional strictness checks.
[1] PowerShell is, after all, a shell - but it is also a full-featured scripting language that offers near-unlimited access to the .NET framework.
Reconciling these two personalities is a difficult balancing act, and the shell-like command-invocation syntax is a frequent problem for newcomers with a programming background, given that the rest of the language looks like a traditional programming language and that calling methods on .NET types does use the traditional syntax.
[2] This means preferring PowerShell's cmdlets, functions, and operators to use of the underlying .NET types' methods; doing so also usually provides rewards you with operating at a higher level of abstraction.
I wonder if it is right semantics to have a variable as an argument, something like this:
proc p1 {$aa} {}
I tried it on tclsh, there is no complaint, but the following experiment fails:
% set aa bb
bb
% set bb 200
200
% proc p1 {$aa} {puts $bb}
% p1 bb
can't read "bb": no such variable
Do you see what is wrong?
[UPDATE - after seeing Peter's answer]
I know the upvar semantic, thanks.
My main curiosity is still around using variable as proc argument. I know it is not common, but just cannot help musing what it really can do if the language syntax allows it.
Yes, your upvar example is exactly what I want to explore using a variable as proc argument, but my exploration so far tells me, really, there is no way we can do this because "$" is interpreted as a plain char.
Do debunk me please if I am wrong.
Tcl does not support reference arguments as such: the usual pass-by-reference semantics is too static for Tcl. Instead, the logic of the command can, by use of upvar, dynamically create reference parameters including indirect reference parameters and calculated reference parameters, and also retarget the local name to another external variable. The upvar mechanism may look ungainly, but is very powerful indeed.
(The (edited) remains of my original answer follows:)
The usual idiom for doing this is
proc p varName {
upvar 1 $varName var
puts $var
}
The upvar command looks into another stack frame (in this case 1, which is the caller's stack frame) and makes a variable named $varName (i.e. the variable's name is the value of varName) in that stack frame and a variable named "var" in the command's stack frame refer to the same data object.
I won't explain this further since this is not useful to the asker.
Documentation: proc, puts, upvar
There are cases where it makes sense for the arguments in a procedure creation call to be supplied from a variable. The main example is where you are creating procedures dynamically, calculating the arguments you want to use as you go along.
That's actually a use-case that isn't done very frequently! It's not particularly easy to use well. But I have done it. (OK, that's a method call, but the syntax of formal arguments is shared.)
The main reason that the capability is there is that it's part of Tcl's general syntax. Tcl tries very hard to not have special cases in how it parses things (other than in how a command parses the strings passed into it) and this includes in things that would be very special cases in the enormous majority of other programming languages, such as formal parameter lists to procedures. In Tcl, these are just ordinary values and can be produced using any technique that gives ordinary values.
The usual thing with putting them in braces is just how you do it reliably and is easy to teach. It's also overwhelmingly what people want to do.
All this is independent of the facts that Tcl's commands (including its procedures) can handle variable numbers of arguments (check out the special args parameter and how to specify default values) and that $aa is a legal (but strange) name for a local variable.
This is normal definition of some function as I know:
real function f(x)
real x
f = (sin(x))**2*exp(-x)
end function f
But I want to define a function from some string, for example the program will ask me to write it, and then it will define the function f in a program. Is this possible in Fortran?
What you are looking for is possible in reflective programming languages, and is not possible in Fortran.
Quote from the link above:
A language supporting reflection provides a number of features available at runtime that would otherwise be very obscure to accomplish in a lower-level language. Some of these features are the abilities to:
Discover and modify source code constructions (such as code blocks, classes, methods, protocols, etc.) as a first-class object at runtime.
Convert a string matching the symbolic name of a class or function into a reference to or invocation of that class or function.
Evaluate a string as if it were a source code statement at runtime.
Create a new interpreter for the language's bytecode to give a new meaning or purpose for a programming construct.
I worked on a project once that tried to achieve something similar. We read in a string that contained a string with named variables and mathematical operations (a function if you will). In this string the variables then got replaced by their numerical values and the terms were evaluated.
The basic idea is not to too difficult, but it requires a lot of string manipulations - and it is not a function in the context of a programming language.
We did it like this:
Recursively divide the string at +,-,/,*, but remember to honor brackets
If this is not possible (without violating bracketing), evaluate the remaining string:
Does it contain a mathematical expression like cos? Yes => recurse into arguments
No => evaluate the mathematical expression (no variables allowed, but they got replaced)
This works quite well, but it requires:
Splitting strings
Matching in strings
Replacing strings with other strings, etc.
This is not trivial to do in Fortran, so if you have other options (like calling an external tool/script that returns the value), I would look into that - especially if you are new to Fortran!
Is there any way to define an Erlang function from within the Erlang shell instead of from an erl file (aka a module)?
Yes but it is painful. Below is a "lambda function declaration" (aka fun in Erlang terms).
1> F=fun(X) -> X+2 end.
%%⇒ #Fun <erl_eval.6.13229925>
Have a look at this post. You can even enter a module's worth of declaration if you ever needed. In other words, yes you can declare functions.
One answer is that the shell only evaluates expressions and function definitions are not expressions, they are forms. In an erl file you define forms not expressions.
All functions exist within modules, and apart from function definitions a module consists of attributes, the more important being the modules name and which functions are exported from it. Only exported functions can be called from other modules. This means that a module must be defined before you can define the functions.
Modules are the unit of compilation in erlang. They are also the basic unit for code handling, i.e. it is whole modules which are loaded into, updated, or deleted from the system. In this respect defining functions separately one-by-one does not fit into the scheme of things.
Also, from a purely practical point of view, compiling a module is so fast that there is very little gain in being able to define functions in the shell.
This depends on what you actually need to do.
There are functions that one could consider as 'throwaways', that is, are defined once to perform a test with, and then you move on. In such cases, the fun syntax is used. Although a little cumbersome, this can be used to express things quickly and effectively. For instance:
1> Sum = fun(X, Y) -> X + Y end.
#Fun<erl_eval.12.128620087>
2> Sum(1, 2).
3
defines an anonymous fun that is bound to the variable (or label) Sum. Meanwhile, the following defines a named fun, called F, that is used to create a new process whose PID (<0.80.0>) is bound to Pid. Note that F is called in a tail recursive fashion in the second clause of receive, enabling the process to loop until the message stop is sent to it.
3> Pid = spawn(fun F() -> receive stop -> io:format("Stopped~n"); Msg -> io:format("Got: ~p~n", [Msg]), F() end end).
<0.80.0>
4> Pid ! hello.
hello
Got: hello
5> Pid ! stop.
Stopped
stop
6>
However you might need to define certain utility functions that you intend to use over and over again in the Erlang shell. In this case, I would suggest using the user_default.erl file together with .erlang to automatically load these custom utility functions into the Erlang shell as soon as this is launched. For instance, you could write a function that compiles all the Erlang files in living in the current directory.
I have written a small guide on how to do this on this GitHub link. You might find it helpful and instructive.
If you want to define a function on the shell to use it as macro (because it encapsulates some functionality that you need frequently), have a look at
https://erldocs.com/current/stdlib/shell_default.html