How to manipulate the value of variables based on an array of symbols in Julia? - metaprogramming

This is somewhat related to David's question here. I'm interested in looping over an array of symbols (pointing to objects) and performing an operation on each step of the loop. For example, suppose I want to write a function that looks at a bunch of variables and converts any scalars to one-element arrays.
widget = "a scalar"
dohickey = ["item 1", "item 2"]
gizmo = "another scalar"
theVariables = [:widget, :dohickey, :gizmo]
for thisVariable in theVariables
if !(typeof(eval(thisVariable)) <: Array)
println("Found a scalar")
#Make it a vector here
end
end
Ideally at the end of this we would have the following
widget = ["a scalar"]
dohickey = ["item 1", "item 2"]
gizmo = ["another scalar"]
This is a fairly lame example, but how can this be done? I thought I should be able to use something like
:($thisVariable) = [:($thisVariable)]
but I can't get it to work.
Edit: DSM's solution below works for the case described above, but in my actual usage I want to do this inside a function. If I define
function getsort(; arga="", argb="", argc="")
filterSpecs = [:arga, :argb, :argc]
for ts in filterSpecs
if !(typeof($ts) <: Array)
#nothing here
end
end
end
and then call getsort() it throws
error compiling getsort: error compiling __getsort#31__: syntax: prefix $ in non-quoted expression
I'm clearly missing something about metaprogramming magic.

This is more a followup to #DSM's answer but writing code in comments is hard. A word of caution: eval evaluates in the global scope which can lead to strange things
julia> a = 3
3
julia> function f(a)
eval(:(a = 1))
println(a)
end
f (generic function with 1 method)
julia> f(a)
3
julia> a
1

From the code generation section of the docs, I think all you need is
#eval $thisVariable = [$thisVariable]
For example:
widget = "a scalar"
dohickey = ["item 1", "item 2"]
gizmo = "another scalar"
theVariables = [:widget, :dohickey, :gizmo]
for thisVariable in theVariables
if !(typeof(eval(thisVariable)) <: Array)
println("Found a scalar")
#eval $thisVariable = [$thisVariable]
end
end
which gives me
Found a scalar
Found a scalar
julia> widget
1-element Array{ASCIIString,1}:
"a scalar"
julia> dohickey
2-element Array{ASCIIString,1}:
"item 1"
"item 2"
julia> gizmo
1-element Array{ASCIIString,1}:
"another scalar"

Are you sure you need a macro here? If you're looking to just handle your function inputs you can do something like:
julia> function newDictOfArrays(d)
wrapped=false
for (k,v) in d
if !(typeof(v) <: AbstractArray)
wrapped = true
d[k] = [v]
end
end
(wrapped, d)
end
newDictOfArrays (generic function with 1 method)
julia> function f(; kwargs...)
(wrapped, d) = newDictOfArrays(Dict(kwargs))
if wrapped
return f(;d...)
end
println("continue knowing all keyword args have been wrapped: $kwargs")
end
f (generic function with 1 method)
julia> f(a=1, b=[2])
continue knowing all keyword args have been wrapped: Any[(:a,[1]),(:b,[2])]
julia> f(a=[1], b=[2])
continue knowing all keyword args have been wrapped: Any[(:a,[1]),(:b,[2])]
newDictOfArrays checks all members of a dictionary for values that are not subtypes of AbstractArray, and overrides that item with a wrapped value. In f, if anything was wrapped, it re-calls the same function again with the new dictionary passed as keyword arguments. No macros, eval, etc, although you could consider writing a macro that injects the code into f automatically if need this frequently.

Related

how to return a new instance in julia

how can I return a new instance from a struct within a function in Julia?
function generateField(type, default, description, max, min)
return Field{type}(default,description,min,max)
end
I have a struct called Field. I just used Java logic hier and it did not work for sure :)
struct Field{T}
type::T
default::T
description::String
min::T
max::T
function Field{T}(description,min,max) where {T}
new{T}(description, min, max)
end
end
Just use deepcopy(obj) - it will make a copy of your struct object (assuming this is what you need):
julia> mutable struct Field2{T<:Real}
a::T
b::Vector{Float64}
end
julia> x = Field2{Int}(5,[4.5])
Field2{Int64}(5, [4.5])
julia> y = deepcopy(x)
Field2{Int64}(5, [4.5])
julia> y == x
false
Note that x and y point to different variables and hence x == y yields false. To compare by value one would need to iterate over all struct fields.
For this struct a function generating it could be defined as :
function f(a::T, b::Vector{Float64}) where T <: Real
return Field2{T}(a,b)
end
And used as:
julia> f(1//2, [3.5])
Field2{Rational{Int64}}(1//2, [3.5])
Finally, note that the function generating an object can have the same name as its type - in that case you are generating new constructor:
julia> Field2(a::T) where T<:Real = Field2{T}(a,Int[]);
julia> Field2(2)
Field2{Int64}(2, Float64[])

Strings in Python are immutable? [duplicate]

My understanding was that Python strings are immutable.
I tried the following code:
a = "Dog"
b = "eats"
c = "treats"
print a, b, c
# Dog eats treats
print a + " " + b + " " + c
# Dog eats treats
print a
# Dog
a = a + " " + b + " " + c
print a
# Dog eats treats
# !!!
Shouldn't Python have prevented the assignment? I am probably missing something.
Any idea?
First a pointed to the string "Dog". Then you changed the variable a to point at a new string "Dog eats treats". You didn't actually mutate the string "Dog". Strings are immutable, variables can point at whatever they want.
The string objects themselves are immutable.
The variable, a, which points to the string, is mutable.
Consider:
a = "Foo"
# a now points to "Foo"
b = a
# b points to the same "Foo" that a points to
a = a + a
# a points to the new string "FooFoo", but b still points to the old "Foo"
print a
print b
# Outputs:
# FooFoo
# Foo
# Observe that b hasn't changed, even though a has.
The variable a is pointing at the object "Dog". It's best to think of the variable in Python as a tag. You can move the tag to different objects which is what you did when you changed a = "dog" to a = "dog eats treats".
However, immutability refers to the object, not the tag.
If you tried a[1] = 'z' to make "dog" into "dzg", you would get the error:
TypeError: 'str' object does not support item assignment"
because strings don't support item assignment, thus they are immutable.
Something is mutable only when we are able to change the values held in the memory location without changing the memory location itself.
The trick is: If you find that the memory location before and after the change are the same, it is mutable.
For example, list is mutable. How?
>> a = ['hello']
>> id(a)
139767295067632
# Now let's modify
#1
>> a[0] = "hello new"
>> a
['hello new']
Now that we have changed "a", let's see the location of a
>> id(a)
139767295067632
so it is the same as before. So we mutated a. So list is mutable.
A string is immutable. How do we prove it?
> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------
we get
TypeError: 'str' object does not support item assignment
So we failed mutating the string. It means a string is immutable.
In you reassigning, you change the variable to point to a new location itself. Here you have not mutated the string, but mutating the variable itself. The following is what you are doing.
>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808
id before and after reassignment is different, so it this proves that you are actually not mutating, but pointing the variable to new location. Which is not mutating that string, but mutating that variable.
Consider:
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='asdf'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x1091aab90>
>>> a='qwer'
>>> a.__repr__
<method-wrapper '__repr__' of str object at 0x109198490>
Notice that the hex memory location did not change when I stored the same value in the variable twice. It did change when I stored a different value. The string is immutable. Not because of zealotry, but because you pay the performance penalty of creating a new object in memory. The variable a is just a label pointing to that memory address. It can be altered to point to anything.
A variable is just a label pointing to an object. The object is immutable, but you can make the label point to a completely different object if you want to.
The statement a = a + " " + b + " " + c can be broken down based upon pointers.
a + " " says give me what a points to, which can't be changed, and add " " to my current working set.
memory:
working_set = "Dog "
a = "Dog"
b = "eats"
c = "treats"
+ b says give me what b points to, which can't be changed, and add it to current working set.
memory:
working_set = "Dog eats"
a = "Dog"
b = "eats"
c = "treats"
+ " " + c says add " " to the current set. Then give me what c points to, which can't be changed, and add it to current working set.
memory:
working_set = "Dog eats treats"
a = "Dog"
b = "eats"
c = "treats"
Finally, a = says set my pointer to point to the resulting set.
memory:
a = "Dog eats treats"
b = "eats"
c = "treats"
"Dog" is reclaimed, because no more pointers connect to it's chunk of memory. We never modified the memory section "Dog" resided in, which is what is meant by immutable. However, we can change which labels, if any, point to that section of memory.
There is a difference between data and the label it is associated with. For example when you do
a = "dog"
the data "dog" is created and put under the label a. The label can change but what is in the memory won't. The data "dog" will still exist in memory (until the garbage collector deletes it) after you do
a = "cat"
In your programm a now ^points to^ "cat" but the string "dog" hasn't changed.
l = [1,2,3]
print id(l)
l.append(4)
print id(l) #object l is the same
a = "dog"
print id(a)
a = "cat"
print id(a) #object a is a new object, previous one is deleted
Python strings are immutable. However, a is not a string: it is a variable with a string value. You can't mutate the string, but can change what value of the variable to a new string.
Python string objects are immutable.
Example:
>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'
In this example we can see that when we assign different value in a it doesn't modify.A new object is created.
And it can't be modified.
Example:
>>> a[0] = 'c'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
**TypeError**: 'str' object does not support item assignment
A error occurs.
Variables can point to anywhere they want..
An error will be thrown if you do the following:
a = "dog"
print a #dog
a[1] = "g" #ERROR!!!!!! STRINGS ARE IMMUTABLE
'mutable' means that we can change the content of the string,
'immutable' means that we can't add an extra string.
a = 'dog'
address = id(a)
print(id(a))
a = a + 'cat'
print(id(a)) #Address changes
import ctypes
ctypes.cast(address, ctypes.py_object).value #value at old address is intact
>>> a = 'dogs'
>>> a.replace('dogs', 'dogs eat treats')
'dogs eat treats'
>>> print a
'dogs'
Immutable, isn't it?!
The variable change part has already been discussed.
Consider this addition to your example
a = "Dog"
b = "eats"
c = "treats"
print (a,b,c)
#Dog eats treats
d = a + " " + b + " " + c
print (a)
#Dog
print (d)
#Dog eats treats
One of the more precise explanations I found in a blog is:
In Python, (almost) everything is an object. What we commonly refer to as "variables" in Python are more properly called names. Likewise, "assignment" is really the binding of a name to an object. Each binding has a scope that defines its visibility, usually the block in which the name originates.
Eg:
some_guy = 'Fred'
# ...
some_guy = 'George'
When we later say some_guy = 'George', the string object containing 'Fred' is unaffected. We've just changed the binding of the name some_guy. We haven't, however, changed either the 'Fred' or 'George' string objects. As far as we're concerned, they may live on indefinitely.
Link to blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/
Adding a bit more to above-mentioned answers.
id of a variable changes upon reassignment.
>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776
Which means that we have mutated the variable a to point to a new string. Now there exist two string(str) objects:
'initial_string' with id = 139982120425648
and
'new_string' with id = 139982120425776
Consider the below code:
>>> b = 'intitial_string'
>>> id(b)
139982120425648
Now, b points to the 'initial_string' and has the same id as a had before reassignment.
Thus, the 'intial_string' has not been mutated.
The built-in function id() returns the identity of an object as an integer. This integer usually corresponds to the object’s location in memory.
\>>a='dog'
\>>print(id(a))
139831803293008
\>>a=a+'cat'
\>>print(id(a))
139831803293120
Initially, 'a' is stored in 139831803293008 memory location, as the string object is immutable in python if you try to modify and reassign the reference will be removed and will be a pointer to a new memory location(139831803293120).
Summarizing:
a = 3
b = a
a = 3+2
print b
# 5
Not immutable:
a = 'OOP'
b = a
a = 'p'+a
print b
# OOP
Immutable:
a = [1,2,3]
b = range(len(a))
for i in range(len(a)):
b[i] = a[i]+1
This is an error in Python 3 because it is immutable. And not an error in Python 2 because clearly it is not immutable.
We r just concatenate the two string values. We never change the value of (a). Just now (a) represent another memory block that has "dogdog" value. Because in the backend, one variable never represent two memory blocks at same time. The value of (a) before concatenation was "dog". But after that (a) represent the "dogdog", because now (a) in backend rep. the block that has "dogdog" value. And "dog" is rep. by (b) and "dog" isn't counted as garbage value until (b) represent the "dog".
The confusion is we represent the memory blocks(that contain data or info.) in backend with same variable name.
You can make a numpy array immutable and use the first element:
numpyarrayname[0] = "write once"
then:
numpyarrayname.setflags(write=False)
or
numpyarrayname.flags.writeable = False
This image gives the answer. Please read it.

what happens in python when using word in

what happens when I execute this code with word in (assume I created class A), more specifically how objects are compared:
my_list = [A(1), A(2), A(3)]
A(1) in my_list # returns True
A(-3) in my_list # returns False
I am interested in technical details of what is going on (if hash or repr method is called etc.) so I would be very interested in expert level answer to this question
The expression x in y can be thought of as doing:
any(x is e or x == e for e in y)
Note that it may be the case that A(12) != A(12), if you have not defined equality for the class A.

In Lua, how do you find out the key an object is stored in?

How would you print() out or find out the index of an object?
For example, if I spawned 20 random rock objects on screen into an array RockTable = {};
Like this RockTable[#RockTable + 1] = rock;
And all 20 rocks are displayed on screen how would I find out what key or index each rock has by clicking on them?
I'm using Corona SDK.
Any help would be greatly appreciated.
Invert the table:
function table_invert(t)
local u = { }
for k, v in pairs(t) do u[v] = k end
return u
end
You can then use the inverted table to find the index.
I find this function so useful that it goes into my permanent "Lua utilities" libraries.
There's another way you can do it, using metamethods.
[Edited to allow you to remove values too]
t = {} -- Create your table, can be called anything
t.r_index = {} -- Holds the number value, i.e. t[1] = 'Foo'
t.r_table = {} -- Holds the string value, i.e. t['Foo'] = 1
mt = {} -- Create the metatable
mt.__newindex = function (self, key, value) -- For creating the new indexes
if value == nil then -- If you're trying to delete an entry then
if tonumber(key) then -- Check if you are giving a numerical index
local i_value = self.r_index[key] -- get the corrosponding string index
self.r_index[key] = nil -- Delete
self.r_table[i_value] = nil
else -- Otherwise do the same as above, but for a given string index
local t_value = self.r_table[key]
self.r_index[t_value] = nil
self.r_table[key] = nil
end
else
table.insert(self.r_index, tonumber(key), value) -- For t[1] = 'Foo'
self.r_table[value] = key -- For t['Foo'] = 1
end
end
mt.__index = function (self, key) -- Gives you the values back when you index them
if tonumber(key) then
return (self.r_index[key]) -- For For t[1] = 'Foo'
else
return (self.r_table[key]) -- For t['Foo'] = 1
end
end
setmetatable(t, mt) -- Creates the metatable
t[1] = "Rock1" -- Set the values
t[2] = "Rock2"
print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])
t[1] = nil
print(t[1], t[2]) -- And *should* proove that it works
print(t['Rock1'], t['Rock2'])
It's more versatile as you can copy the t value and take it with you; it also means that you only have to play around with the one variable most of the time - hopefully should reduce the likelihood of you trying to access the wrong thing.
The simplest way is to add an "index" property to each rock:
RockTable = {}
for i=1,20 do
local rock
-- do your thing that generates a new 'rock' object
rock.index = #RockTable + 1
RockTable[rock.index] = rock
end
If you use a touch listener method, you can retrieve the rock this way:
function touchListener( event )
local rock = event.target
local rockIndex = rock.index
-- ...
end
It is true that you can maintain a second table with indices, but I find my method cleaner - when it is time to remove things, you only have to worry about one table, the main one.
I have a question though: why do you need to retrieve that index? In most cases, well designed event listener functions are enough, you don't need to "find" your objects. Of course I lack information on what you are trying to do, but it is possible that you are over-complicating things.
you could do something like this to save you some trouble of constantly looping over a table to find the index...
RockTable = {}
RockIndicies = {}
for i = 1, 20 do
idx = #RockTable + 1
RockTable[idx] = rock
RockIndicies[rock] = idx
end
then when you need to know the index, you can just use the rock you have to index RockIndices to quickly get it. If you 'delete' a rock, you'd want to make sure to remove it in both places.
Unfortunately you'd need to brute the table, to my knowledge. Although, to know that one was clicked, wouldn't you need to be looping them in some way anyway; and therefore already know the index?
Edit
Oh, unless Corona has some sort of callback event for clicking. I've never used it, I've got experience in Lua though.
You could maybe do a backwards reference, like so:
Rocks = {a rock, a rockB, a rockC}
RocksB = {[a rock] = 1, [a rockB] = 2, [a rockC] = 3}
Then just say rockNum = RocksB[rock]
I'm pretty certain that should work but I can't guarantee it, worth a try though.
Edit2
The brute method would look somewhat like:
function getRock(rock)
for _,v in pairs(rocks) do
if (v == rock)
return _
end
end
return "Rock does not exist."
end

How to concat string + i?

for i=1:N
f(i) = 'f'+i;
end
gives an error in MatLab. What's the correct syntax to initialize an array with N strings of the pattern fi?
It seems like even this is not working:
for i=1:4
f(i) = 'f';
end
You can concatenate strings using strcat. If you plan on concatenating numbers as strings, you must first use num2str to convert the numbers to strings.
Also, strings can't be stored in a vector or matrix, so f must be defined as a cell array, and must be indexed using { and } (instead of normal round brackets).
f = cell(N, 1);
for i=1:N
f{i} = strcat('f', num2str(i));
end
For versions prior to R2014a...
One easy non-loop approach would be to use genvarname to create a cell array of strings:
>> N = 5;
>> f = genvarname(repmat({'f'}, 1, N), 'f')
f =
'f1' 'f2' 'f3' 'f4' 'f5'
For newer versions...
The function genvarname has been deprecated, so matlab.lang.makeUniqueStrings can be used instead in the following way to get the same output:
>> N = 5;
>> f = strrep(matlab.lang.makeUniqueStrings(repmat({'f'}, 1, N), 'f'), '_', '')
f =
1×5 cell array
'f1' 'f2' 'f3' 'f4' 'f5'
Let me add another solution:
>> N = 5;
>> f = cellstr(num2str((1:N)', 'f%d'))
f =
'f1'
'f2'
'f3'
'f4'
'f5'
If N is more than two digits long (>= 10), you will start getting extra spaces. Add a call to strtrim(f) to get rid of them.
As a bonus, there is an undocumented built-in function sprintfc which nicely returns a cell arrays of strings:
>> N = 10;
>> f = sprintfc('f%d', 1:N)
f =
'f1' 'f2' 'f3' 'f4' 'f5' 'f6' 'f7' 'f8' 'f9' 'f10'
Using sprintf was already proposed by ldueck in a comment, but I think this is worth being an answer:
f(i) = sprintf('f%d', i);
This is in my opinion the most readable solution and also gives some nice flexibility (i.e. when you want to round a float value, use something like %.2f).
according to this it looks like you have to set "N" before trying to use it and it looks like it needs to be an int not string? Don't know much bout MatLab but just what i gathered from that site..hope it helps :)
Try the following:
for i = 1:4
result = strcat('f',int2str(i));
end
If you use this for naming several files that your code generates, you are able to concatenate more parts to the name. For example, with the extension at the end and address at the beginning:
filename = strcat('c:\...\name',int2str(i),'.png');

Resources