Related
This question already has an answer here:
Julia: invoke a function by a given string
(1 answer)
Closed 6 years ago.
I know that you can call functions using their name as follows
f = x -> println(x)
y = :f
eval(:($y("hi")))
but this is slow since it is using eval is it possible to do this in a different way? I know it's easy to go the other direction by just doing symbol(f).
What are you trying to accomplish? Needing to eval a symbol sounds like a solution in search of a problem. In particular, you can just pass around the original function, thereby avoiding issues with needing to track the scope of f (or, since f is just an ordinary variable in your example, the possibility that it would get reassigned), and with fewer characters to type:
f = x -> println(x)
g = f
g("hi")
I know it's easy to go the other direction by just doing symbol(f).
This is misleading, since it's not actually going to give you back f (that transform would be non-unique). But it instead gives you the string representation for the function (which might happen to be f, sometimes). It is simply equivalent to calling Symbol(string(f)), since the combination is common enough to be useful for other purposes.
Actually I have found use for the above scenario. I am working on a simple form compiler allowing for the convenient definition of variational problems as encountered in e.g. finite element analysis.
I am relying on the Julia parser to do an initial analysis of the syntax. The equations entered are valid Julia syntax, but will trigger errors on execution because some of the symbols or methods are not available at the point of the problem definition.
So what I do is roughly this:
I have a type that can hold my problem description:
type Cmd f; a; b; end
I have defined a macro so that I have access to the problem description AST. I travers this expression and create a Cmd object from its elements (this is not completely unlike the strategy behind the #mat macro in MATLAB.jl):
macro m(xp)
c = Cmd(xp.args[1], xp.args[3], xp.args[2])
:($c)
end
At a later step, I run the Cmd. Evaluation of the symbols happens only at this stage (yes, I need to be careful of the evaluation context):
function run(c::Cmd)
xp = Expr(:call, c.f, c.a, c.b)
eval(xp)
end
Usage example:
c = #m a^b
...
a, b = 2, 3
run(c)
which returns 9. So in short, the question is relevant in at least some meta-programming scenarios. In my case I have to admit I couldn't care less about performance as all of this is mere preprocessing and syntactic sugar.
If you look at Rust, Go, Swift, TypeScript and a few others, and compare them to C/C++, the first thing that I noticed was how the types have moved positions.
int one = 1;
In comparsion to:
let one:int = 1;
My question: Why?
To me, personally, it is weird reading type specifiers that far into the line, since I am very used to them being on the left. So it interests me on why the type specifiers are being moved - and this not being the case with just one, but many modern/new languages that are on the table.
To me, personally, it is weird reading type specifiers that far into the line, since I am very used to them being on the left
And English is the best language because it is the only language where the words are spoken in the same order I think them. One wonders why anyone speaks French at all, with the words all in the wrong order!
So it interests me on why the type specifiers are being moved - and this not being the case with just one, but many modern/new languages that are on the table.
I note that you ignore the existence of the many older languages which use this pattern. Visual Basic (mid 1990s) immediately comes to mind.
Function F(x As String) As Object
Pascal, 1970s:
var
Set1 : set of 1..10;
Simply-typed lambda calculus, a programming language invented before computers, in the 1940s:
λx:S.λy:T:S-->T-->S
The whole ML family. I could go on. There are plenty of very old languages that use the types on the right convention.
But we can get far older than the 1940s. When you say in mathematics f : Q --> R, you are putting the name of the function on the left and the type -- a map from Q to R -- on the right. When you say x∈R to indicate that x is a real, you're putting the type on the right. "Type on the right" predates type on the left in C by literally centuries. This is not anything new!
In fact the "types on the left" syntax is the weird one! It just seems natural to you because you happen to have used a language that uses this convention in your formative years.
The types on the right syntax is much superior, for numerous reasons. Just a few:
var x : int = 1;
function y(z : int) : string { ... }
emphasizes that x is a variable and y is a function. If the type comes to the left and you see int y then you don't know whether it is a function or a variable until later. This makes programs harder for humans to read, which is bad enough. As a compiler developer, let me tell you it is quite inconvenient that the type comes on the left in C#. (I could point out numerous inconsistencies in how C# syntax deals with the positions of types.)
Another reason: In the "type on the right" syntax you can make types optional. If you have
var x : int = 1;
then you can easily say "well, we can infer the int, and so eliminate it"
var x = 1;
but if the int is on the left, then what do you do?
Inverting this: you mention TypeScript. TypeScript is a gradually-typed JavaScript. The convention in JavaScript is already
var x = 1;
function f(y) { }
Given that, plainly it is easier to modify both existing code, and the language as a whole, to introduce optional type elements on the right than it would be to make the "var" and "function" keywords replaced by a type.
Consider also the positioning. When you say:
int x = 1;
then the two things that must be consistent -- the type and the initializer -- are as far apart as they possibly can be. With var x : int = 1; they are side by side. And in
int f() {
...
...
return 123;
}
what have we got? The return is logically as far to the right as possible, so why does the function declaration move the type of the return as far to the left as possible?" With the type on the right syntax we have this nice flow:
function f(x : string) : int
{ ... ... ... return 123; }
What happens in a function call? The flow of the declaration is now the same as the flow of control: the things on the left -- initialization of formal parameters -- happens first, and the things on the right -- production of a return value -- happen last.
I could go on at some additional length pointing out how the C style gets it completely backwards, but it is late. Summing up: first, type on the right is superior in almost every possible way, and second, it is very, very old. New languages which use this convention are the ones that are being consistent with traditional practice.
If you do a web search, it is not hard to find the developers of newer languages answering this question in their own words. For example, the Go developers have a FAQ entry on this, as well as an entire article on their language blog. Many programmers are so used to C-like languages that any alternative seems weird, so this question tends to come up a lot...
However, you could argue that the C type declaration syntax itself is odd at best. The pattern-like features for pointers and function types become awkward and unintuitive very quickly, and were never developed as part of, or into, any kind of more general pattern-matching facility. For the sake of familiarity, they were adopted to a greater or lesser degree by many successive C-like languages, but the feature itself sticks out as more of a failed experiment that we have to live with for the sake of backwards compatibility.
One advantage of extricating yourself from C type syntax is that it makes it easier to use types in more places than just declarations. If you can place types conveniently wherever they make sense, you can use your types as annotation, as described in the Swift documentation.
My problem (in Mathematica) is referring to variables given in a particular array and manipulating them in the following manner (as an example):
Inputs: vars={x,y,z}, system=some ODE like x^2+3*x*y+...etc
(note that I haven't actually created variables x y and z)
Aim:
To assign values to the variables in the list "var" with the intention of inputting these values into the system of ODEs. Then, once I am done, clear the values of the variables in the array vars so that it is in its original form {x,y,z} (and not something like {x,1,3} where y=1 and z=3). I want to do this by referring to the positional elements of vars (I aim not to know that x, y and z are the actual variables).
The reason why: I am trying to write a program that can have any number of variables and ODEs as defined by the user. Since the number of variables and the actual letters used for them are unknown, it is necessary to perform manipulations with the array itself.
Attempt:
A fixed number of variables is easy. For the arbitrary case, I have tried modules and blocks, but with no success. Consider the following code:
Clear[x,y,z,vars,svars]
vars={x,y,z}
svars=Map[ToString,vars]
Module[{vars=vars,svars=svars},
Symbol[svars[[1]]]//Evaluate=1
]
then vars={1,y,z} and not {x,y,z} after running this. I have done functional programming with lists, atoms etc. Thus is makes sense to me that vars is changed afterwards, because I have changed x and not vars. However, I cannot get "x" in the list of variables to remain local. Of course I could put in "x" itself, but that is particular to this specific case. I would prefer to put something like:
Clear[x,y,z,vars,svars]
vars={x,y,z}
svars=Map[ToString,vars]
Module[{vars=vars,svars=svars, vars[[1]]},
Symbol[svars[[1]]]//Evaluate=1
]
which of course doesn't work because vars[[1]] is not a symbol or an assignment to a symbol.
Other possibilities:
I found a function
assignToName[name_String, value_] :=
ToExpression[name, InputForm, Function[var, var = value, HoldAll]]
which looked promising. Basically name_String is the name of the variable and value is its new value. I attempted to do:
vars={x,y,z}
svars=Map[ToString,vars]
vars[[1]]=//Evaluate=1
assignToName[svars[[1]],svars[[1]]]
but then something likeD[x^2, vars[[1]]] doesn't work (x is not a valid variable).
If I am missing something, or if perhaps I am going down the wrong path, I'm open to trying other things.
Thanks.
I can't say that I followed your train(s) of thought very well, so these are fragments which might help you to answer your own questions than a coherent and fully-formed answer. But to answer your final 'question', I think you may be going down some wrong path(s).
In passing, note that evaluating the expression
vars = {x,y,z}
does in fact define those three variables though it doesn't define any rewrite rules (such as values) for them.
Given a polynomial poly you can extract the variables in it with the function Variables[poly] so something like
Variables[x^2+3*x*y]
should return
{x,y}
Note that I write 'should' rather than does because I don't have Mathematica on this machine so my syntax may be a bit wonky. Note also that your example ODE is nothing of the sort but it strikes me that you can probably write a wrapper to manipulate an ODE into a form from which Variables can extract the variables. Mathematica offers a lot of other functions for picking expressions apart and re-assembling them, follow the trails from Variables. It often allows the use of functions defined on Lists on expressions with other heads too so it's always worth experimenting a bit.
There are a couple of widely applicable ways to avoid setting values of variables in Mathematica. For instance, you could write
x^2+3*x*y/.{x->2,y->3}
which will evaluate to
22
but not set values for x and y. This is a very simple example of using (sets of) replacement rules for temporary assignment of values to variables
The other way to avoid setting values for variables is to define functions using Modules or Blocks both of which define their own contexts. The documentation will tell you all about these two and the differences between them.
I can't help thinking that all your clever tricks using Symbol, ToExpression and ToString are a bit beside the point. Spend some time familiarising yourself with Mathematica's in-built functionality before going further down that route, you may well find you don't need to.
Finally, writing, in any language, expressions such as
vars=vars,svars=svars
will lead to madness. It may be syntactically correct, you may even be able to decrypt the semantics when you first write code like that, but in a week's time you will curse your younger self for writing it.
I am currently studying the small-step semantics using Context- Environment machine for lambda calculus.
In this kind of machine, or say interpreter, the definition of the closure is open lambda terms paired with an environment component that defines the meaning of free variables in the closure.
When defining the environment component, the literature says:
ρ ∈ Env = Var ⇀ Clo.
which is to map an variable to a closure.
My question is:
Why closure? It is not straightforward to understand.
For example, you can imagine:
According to the definition of closure, every expression has its environment, and thus a closure, then if the current expression to evaluate is a variable v, then we can reference to its environment for v, which will return a closure? What's that? If the variable's value is 5, why not just give me 5, rather than a closure?
Those examples are often defined in the context of λ-calculus without
constants :
terms ::=
| x variable
| t₁ t₂ application
| λx.t abstraction
In this case, only abstractions are values : the only values (normal
forms of a closed terms) are of the form λx.t; indeed, x is not
a closed term and t₁ t₂ can be further reduced.
When using an (t,ρ) term-environment pair (the idea is that ρ
keeps definitions for free variables of t, instead of substituting
them away which is a costly operation), the values in ρ may have free
variables themselves, and therefore need to carry their own
environment : environment should be Var → (Value * Env). As in this
restricted example, the only possible values are abstractions, we name
a pair of a lambda and its environment a "closure", hence Var → Clo.
Now you may want to add other things to your language, such as
constants (5, true, etc.), pairs, let-definitions, continuations,
etc. The definition of terms will be extended in each case, and the
definition of values may also change, for example 2 + 3 won't be
a value but 5 will. Value may or may not capture variables from the
environment : (λf.f x) does, but 5 doesn't. However, we keep the
uniform definition of Env := Var → (Value * Env), so that we don't
have to distinguish between those.
You don't actually need the captured environment to be exactly the
same as the environment you had at the time of the value
construction. You only need to keep bindings for the value that are
actually captured in the value, such as x in (λf. f x) (this is
called "weakening"). In particular, you can always express the
"closure" for 5 as (5, ∅).
I just came across this question in the Go FAQ, and it reminded me of something that's been bugging me for a while. Unfortunately, I don't really see what the answer is getting at.
It seems like almost every non C-like language puts the type after the variable name, like so:
var : int
Just out of sheer curiosity, why is this? Are there advantages to choosing one or the other?
There is a parsing issue, as Keith Randall says, but it isn't what he describes. The "not knowing whether it is a declaration or an expression" simply doesn't matter - you don't care whether it's an expression or a declaration until you've parsed the whole thing anyway, at which point the ambiguity is resolved.
Using a context-free parser, it doesn't matter in the slightest whether the type comes before or after the variable name. What matters is that you don't need to look up user-defined type names to understand the type specification - you don't need to have understood everything that came before in order to understand the current token.
Pascal syntax is context-free - if not completely, at least WRT this issue. The fact that the variable name comes first is less important than details such as the colon separator and the syntax of type descriptions.
C syntax is context-sensitive. In order for the parser to determine where a type description ends and which token is the variable name, it needs to have already interpreted everything that came before so that it can determine whether a given identifier token is the variable name or just another token contributing to the type description.
Because C syntax is context-sensitive, it very difficult (if not impossible) to parse using traditional parser-generator tools such as yacc/bison, whereas Pascal syntax is easy to parse using the same tools. That said, there are parser generators now that can cope with C and even C++ syntax. Although it's not properly documented or in a 1.? release etc, my personal favorite is Kelbt, which uses backtracking LR and supports semantic "undo" - basically undoing additions to the symbol table when speculative parses turn out to be wrong.
In practice, C and C++ parsers are usually hand-written, mixing recursive descent and precedence parsing. I assume the same applies to Java and C#.
Incidentally, similar issues with context sensitivity in C++ parsing have created a lot of nasties. The "Alternative Function Syntax" for C++0x is working around a similar issue by moving a type specification to the end and placing it after a separator - very much like the Pascal colon for function return types. It doesn't get rid of the context sensitivity, but adopting that Pascal-like convention does make it a bit more manageable.
the 'most other' languages you speak of are those that are more declarative. They aim to allow you to program more along the lines you think in (assuming you aren't boxed into imperative thinking).
type last reads as 'create a variable called NAME of type TYPE'
this is the opposite of course to saying 'create a TYPE called NAME', but when you think about it, what the value is for is more important than the type, the type is merely a programmatic constraint on the data
If the name of the variable starts at column 0, it's easier to find the name of the variable.
Compare
QHash<QString, QPair<int, QString> > hash;
and
hash : QHash<QString, QPair<int, QString> >;
Now imagine how much more readable your typical C++ header could be.
In formal language theory and type theory, it's almost always written as var: type. For instance, in the typed lambda calculus you'll see proofs containing statements such as:
x : A y : B
-------------
\x.y : A->B
I don't think it really matters, but I think there are two justifications: one is that "x : A" is read "x is of type A", the other is that a type is like a set (e.g. int is the set of integers), and the notation is related to "x ε A".
Some of this stuff pre-dates the modern languages you're thinking of.
An increasing trend is to not state the type at all, or to optionally state the type. This could be a dynamically typed langauge where there really is no type on the variable, or it could be a statically typed language which infers the type from the context.
If the type is sometimes given and sometimes inferred, then it's easier to read if the optional bit comes afterwards.
There are also trends related to whether a language regards itself as coming from the C school or the functional school or whatever, but these are a waste of time. The languages which improve on their predecessors and are worth learning are the ones that are willing to accept input from all different schools based on merit, not be picky about a feature's heritage.
"Those who cannot remember the past are condemned to repeat it."
Putting the type before the variable started innocuously enough with Fortran and Algol, but it got really ugly in C, where some type modifiers are applied before the variable, others after. That's why in C you have such beauties as
int (*p)[10];
or
void (*signal(int x, void (*f)(int)))(int)
together with a utility (cdecl) whose purpose is to decrypt such gibberish.
In Pascal, the type comes after the variable, so the first examples becomes
p: pointer to array[10] of int
Contrast with
q: array[10] of pointer to int
which, in C, is
int *q[10]
In C, you need parentheses to distinguish this from int (*p)[10]. Parentheses are not required in Pascal, where only the order matters.
The signal function would be
signal: function(x: int, f: function(int) to void) to (function(int) to void)
Still a mouthful, but at least within the realm of human comprehension.
In fairness, the problem isn't that C put the types before the name, but that it perversely insists on putting bits and pieces before, and others after, the name.
But if you try to put everything before the name, the order is still unintuitive:
int [10] a // an int, ahem, ten of them, called a
int [10]* a // an int, no wait, ten, actually a pointer thereto, called a
So, the answer is: A sensibly designed programming language puts the variables before the types because the result is more readable for humans.
I'm not sure, but I think it's got to do with the "name vs. noun" concept.
Essentially, if you put the type first (such as "int varname"), you're declaring an "integer named 'varname'"; that is, you're giving an instance of a type a name. However, if you put the name first, and then the type (such as "varname : int"), you're saying "this is 'varname'; it's an integer". In the first case, you're giving an instance of something a name; in the second, you're defining a noun and stating that it's an instance of something.
It's a bit like if you were defining a table as a piece of furniture; saying "this is furniture and I call it 'table'" (type first) is different from saying "a table is a kind of furniture" (type last).
It's just how the language was designed. Visual Basic has always been this way.
Most (if not all) curly brace languages put the type first. This is more intuitive to me, as the same position also specifies the return type of a method. So the inputs go into the parenthesis, and the output goes out the back of the method name.
I always thought the way C does it was slightly peculiar: instead of constructing types, the user has to declare them implicitly. It's not just before/after the variable name; in general, you may need to embed the variable name among the type attributes (or, in some usage, to embed an empty space where the name would be if you were actually declaring one).
As a weak form of pattern-matching, it is intelligable to some extent, but it doesn't seem to provide any particular advantages, either. And, trying to write (or read) a function pointer type can easily take you beyond the point of ready intelligability. So overall this aspect of C is a disadvantage, and I'm happy to see that Go has left it behind.
Putting the type first helps in parsing. For instance, in C, if you declared variables like
x int;
When you parse just the x, then you don't know whether x is a declaration or an expression. In contrast, with
int x;
When you parse the int, you know you're in a declaration (types always start a declaration of some sort).
Given progress in parsing languages, this slight help isn't terribly useful nowadays.
Fortran puts the type first:
REAL*4 I,J,K
INTEGER*4 A,B,C
And yes, there's a (very feeble) joke there for those familiar with Fortran.
There is room to argue that this is easier than C, which puts the type information around the name when the type is complex enough (pointers to functions, for example).
What about dynamically (cheers #wcoenen) typed languages? You just use the variable.