string as variable name

2,410 views
Skip to first unread message

Mark Vogelsberger

unread,
Oct 3, 2012, 12:23:00 AM10/3/12
to juli...@googlegroups.com
Hi,

imagine I have a string

s="variable"

and I would like to do

variable=42

Is there a way in Julia meta programming to get this done? I.e. to create/assign variables based on strings?

Thanks,
Mark

Jeffrey Sarnoff

unread,
Oct 3, 2012, 1:48:25 AM10/3/12
to juli...@googlegroups.com
here is one way without macros -- others may well have better approaches

julia> function string_as_varname(s::String,v::Any)
         s=symbol(s)
         @eval (($s) = ($v))
       end

julia> string_as_varname("varname",42); varname == 42
true

julia> string_as_varname("varname2","stringval"); varname2 == "stringval"
true

julia> string_as_varname("varname3",[1,2,3]); varname3 == [1,2,3]
true

Jeffrey Sarnoff

unread,
Oct 3, 2012, 2:16:26 AM10/3/12
to juli...@googlegroups.com
Please note that string_as_varname should first validate as a reasonable variable name;
as given, you could write string_as_varname("a b",4) -- and that is probably a bad idea.

Mark Vogelsberger

unread,
Oct 3, 2012, 2:22:16 AM10/3/12
to juli...@googlegroups.com
Thanks that did the job. It's really a please to work with Julia!

Mark

Stefan Karpinski

unread,
Oct 3, 2012, 11:51:15 AM10/3/12
to juli...@googlegroups.com
Thanks, Jeffrey. I would add a cautionary note that using eval like this is usually a bit of a fishy thing to do. I'm not sure what the larger context is, but there's probably a different way to get it done than using eval.

--
 
 
 

John Cowan

unread,
Oct 3, 2012, 1:17:40 PM10/3/12
to juli...@googlegroups.com
On Wed, Oct 3, 2012 at 11:51 AM, Stefan Karpinski <ste...@karpinski.org> wrote:

> Thanks, Jeffrey. I would add a cautionary note that using eval like this is
> usually a bit of a fishy thing to do. I'm not sure what the larger context
> is, but there's probably a different way to get it done than using eval.

Another note is that local variables are not visible to eval; there's
no way to simulate this behavior for local variables, because local
environment frames are not first-class (and a Good Thing Too).

--
GMail doesn't have rotating .sigs, but you can see mine at
http://www.ccil.org/~cowan/signatures

BobC

unread,
Oct 3, 2012, 1:24:10 PM10/3/12
to juli...@googlegroups.com
This is a common practice in Python, especially when testing, where it is common for the entire test code and description to be in a string.

It is also a popular pattern in Python-based serial protocol parsers, where the relevant portion(s) of a command string is used to build the name of the corresponding function to run.  Dynamic name generation eliminates the need for expensive-to-maintain command lookup tables.

Pythonistas also recommend against using eval for this purpose (essentially a side-effect): One preferred way is to query the namespace using getitem().  What is the Julia equivalent?


-BobC

Jeffrey Sarnoff

unread,
Oct 3, 2012, 1:49:22 PM10/3/12
to juli...@googlegroups.com
The safest approach I know is to use a dictionary, add the newly obtained variable name string as a key and the value to be assigned as its value.
Then lookup the value for the named variable through the dictionary.

John Cowan

unread,
Oct 3, 2012, 2:25:57 PM10/3/12
to juli...@googlegroups.com
On Wed, Oct 3, 2012 at 1:24 PM, BobC <rcunn...@nsmsurveillance.com> wrote:

> Pythonistas also recommend against using eval for this purpose (essentially
> a side-effect): One preferred way is to query the namespace using getitem().

That works because both local and global environments are Python
dictionaries -- which is one of the things that keeps Python slow;
they can't be optimized into C/Fortran on-stack variables. (RPython
gets a lot of speed by disallowing such hacks.)

> What is the Julia equivalent?

For local variables there is none.

Cunningham, Robert

unread,
Oct 3, 2012, 2:40:58 PM10/3/12
to juli...@googlegroups.com
I'll bet Python's dictionaries are vastly faster than using eval in Julia!

Plus, PyPy seems to run plenty fast, and it does support this metaphor using regular Python 2.7.x. (RPython is the implementation language of PyPy, and is not intended as an end-user language.)

Even my spell-checker hates 'eval': It thinks 'evil' is the correct spelling.

-BobC
> --
>
>

Mark Vogelsberger

unread,
Oct 3, 2012, 2:54:45 PM10/3/12
to juli...@googlegroups.com
Hi guys,

so what is now the proposed solution for my problem :-). To be specific, here is my code, which is working, but according to the discussion above probably "bad":

header_entries={{"NumPart_Total", 6}}

fname
= construct_filename(base, snapbase, snapnum, filenum)
h5f
= h5open(fname)
grp
= h5f["Header"]

for i = 1:length(header_entries)
println
(header_entries[i][2])
attr
= HDF5Mod.h5a_open(grp, header_entries[i][1], HDF5Mod.H5P_DEFAULT)
var = symbol(header_entries[i][1])
dim
= header_entries[i][2]
dtype
= HDF5Mod.H5T_NATIVE_UINT32
@eval ($var = zeros(Uint32,$dim))
@eval (HDF5Mod.h5a_read($attr, $dtype, $var))
end

close
(h5f)


Thanks,
Mark

Jeffrey Sarnoff

unread,
Oct 3, 2012, 3:41:56 PM10/3/12
to juli...@googlegroups.com
imho
your use of eval is limited and  well-constrained .. it is not "bad"

your question and my response sparked a search for good alternatives
when given, use it -- until then, enjoy the working code

Stefan Karpinski

unread,
Oct 3, 2012, 4:49:18 PM10/3/12
to juli...@googlegroups.com
I see, this is to implement something like Matlab's load functionality. This is definitely a "bad" usage of eval because it means the compiler can't possibly know what the type or even the name of a variable is. It completely defeats any possibility of type inference or other reasoning. It is also the worst kind of side effect: not only is some value affected, but one can't even know statically what the name that is affected is. However, if you want to emulate Matlab's load then clearly this is how you have to do it.

I would argue that one shouldn't emulate the load functionality and should instead pull matrix values out of HDF5 files. Something like this:

X = HDF5Mod.load_from(h5f, Array{Float64}, "var")

That way both the programmer and the compiler know the name and type of the thing being pulled out of the HDF5 file. Obviously, we provide enough rope to implement things like Matlab's load, but I still think it is a sketchy design — magically populating your namespace with who knows what, clobbering who knows which existing bindings [*shudder*].

--
 
 
 

John Cowan

unread,
Oct 3, 2012, 4:54:02 PM10/3/12
to juli...@googlegroups.com
On Wed, Oct 3, 2012 at 2:40 PM, Cunningham, Robert
<RCunn...@nsmsurveillance.com> wrote:
> I'll bet Python's dictionaries are vastly faster than using eval in Julia!

Certainly.

> Plus, PyPy seems to run plenty fast, and it does support
> this metaphor using regular Python 2.7.x. (RPython is the
> implementation language of PyPy, and is not intended as
> an end-user language.)

I realize that. However PyPy is just another Python interpreter, and
is only faster than CPython when its JIT or its better GC come into
play. Its main advantage over CPython is the maintainability of the
interpreter itself.

If you want real speed improvement over CPython, you need to write
your code in the RPython subset and compile it down to C.

Stefan Karpinski

unread,
Oct 3, 2012, 4:57:53 PM10/3/12
to juli...@googlegroups.com
On Wed, Oct 3, 2012 at 4:49 PM, Stefan Karpinski <ste...@karpinski.org> wrote:
X = HDF5Mod.load_from(h5f, Array{Float64}, "var")

Thinking on this, the call should probably be

X = HDF5Mod.load_from(h5f, "var", Array{Float64})

where the type argument is optional.

Tim Holy

unread,
Oct 3, 2012, 5:03:56 PM10/3/12
to juli...@googlegroups.com
Mark, the way hdf5.jl is designed to work is like this:

x = read(obj, "x")

The string refers to a dataset in the file, but the variable on the left hand
side can be whatever you want. In other words,

zz = read(obj, "x")

is perfectly fine. In Matlab this would be the equivalent of

s = load('filename.mat', 'x');
zz = s.x;


There will be a new hdf5.jl available in the next 36 hours or so that should
be capable of directly reading "simple" .mat files that were saved as '-v7.3'
files.

--Tim
> > > To: juli...@googlegroups.com <javascript:>
> > > Subject: Re: [julia-dev] Re: string as variable name
> > >
> > > On Wed, Oct 3, 2012 at 1:24 PM, BobC
> > > <rcunn...@nsmsurveillance.com<javascript:>>> >

Mark Vogelsberger

unread,
Oct 3, 2012, 5:17:04 PM10/3/12
to juli...@googlegroups.com

Am Mittwoch, 3. Oktober 2012 17:03:59 UTC-4 schrieb Tim:
Mark, the way hdf5.jl is designed to work is like this:

x = read(obj, "x")

The string refers to a dataset in the file, but the variable on the left hand
side can be whatever you want. In other words,

zz = read(obj, "x")

is perfectly fine. In Matlab this would be the equivalent of

   s = load('filename.mat', 'x');
   zz = s.x;



Yepp, I know that. It was for convenience that the code stores the attributes under the same variable name. I just have lots of attributes and I wanted to use meta code to avoid too much redundant code.

Thanks,
Mark
 

Stefan Karpinski

unread,
Oct 3, 2012, 5:22:02 PM10/3/12
to juli...@googlegroups.com
A good way to do this might be with a macro:

@h5read h5f x

which could be translated to the more redundant call

x = read(h5f, "x")

This doesn't have the randomly clobbers variables issue since it expands at compile time.

--
 
 
 

Jeffrey Sarnoff

unread,
Oct 3, 2012, 10:34:16 PM10/3/12
to juli...@googlegroups.com
fortunately, I am allowed to be wrong :)

Stefan Karpinski

unread,
Oct 3, 2012, 11:20:49 PM10/3/12
to juli...@googlegroups.com
Fortunately, we all are.

--
 
 
 

Stefan Karpinski

unread,
Oct 3, 2012, 11:22:49 PM10/3/12
to juli...@googlegroups.com
Also, I wouldn't say you're wrong. It's a pretty subjective call. Hence the abundance of quotes around the word "bad" in the above conversation.
Reply all
Reply to author
Forward
0 new messages