python's exec() works oddly inside functions - python-3.x

I (think I) need exec() to procedurally define variables for symbolic computation. The code searches for variables in an expression like 'x/y + z' and generates three variables,
x = sp.sympy('x'), y = sp.sympy('y'), z = sp.sympy('z')(for example).
When I run the code
for char in expr:
if char.isalpha():
exec('%s = sp.symbols("%s")' % (char, char))
print(type(char))
It works just as it should. print(type(char)) just checks if what I wanted to happen happens (it prints <class 'sympy.core.symbol.Symbol'> if it worked).
However, as I need this for a general expr, I need this inside a function. When I do this print(type(char)) outputs <class 'str'>, which means it didn't work.
Also, if I type print(type(char)) inside the exec I get a correct output.
Note: I know exec() is dangerous. I'm just going to use this to have an easier time writing lab reports.

I couldn't think of a way to get it into one line, but I believe this will work:
for char in expr:
if char.isalpha():
exec('%s = sp.symbols("%s")' % (char, char))
exec('temp_type = type(%s)' % char)
print(temp_type)
Alternatively using a dict approach may make it easier in the long run. It avoids the exec.
symbol_dict = dict()
for char in expr:
if char.isalpha():
symbol_dict[char] = sp.symbols(char)
print(symbol_dict[char])

Related

Can I use where in Haskell to find function parameter given the function output?

This is my program:
modify :: Integer -> Integer
modify a = a + 100
x = x where modify(x) = 101
In ghci, this compiles successfully but when I try to print x the terminal gets stuck. Is it not possible to find input from function output in Haskell?
x = x where modify(x) = 101
is valid syntax but is equivalent to
x = x where f y = 101
where x = x is a recursive definition, which will get stuck in an infinite loop (or generate a <<loop>> exception), and f y = 101 is a definition of a local function, completely unrelated to the modify function defined elsewhere.
If you turn on warnings you should get a message saying "warning: the local definition of modify shadows the outer binding", pointing at the issue.
Further, there is no way to invert a function like you'd like to do. First, the function might not be injective. Second, even if it were such, there is no easy way to invert an arbitrary function. We could try all the possible inputs but that would be extremely inefficient.

Why does Python `f-string` + inline for loop create a generator when they're passed as parameter?

I found this example on the internet
def format_attributes(**attributes):
"""Return a string of comma-separated key-value pairs."""
return ", ".join(
f"{param}: {value}"
for param, value in attributes.items()
)
The syntax of the param passed to the join function caught my attention because it's sort of unusual. But it works
Doing some local testing with a minimum codebase I discovered that in:
def foo(res):
return res
print(foo(f"{s}" for s in ["bar"]))
foo's syntax is valid and res ends up being a generator. However, if I try f"{s}" for s in ["bar"] standalone (no function in between), the expression just throws a SyntaxError: invalid syntax.
How come the f-string + for loop is valid and gets converted into a generator? What's happening under the hood when invoking foo function?
These other questions uses the same syntax:
f-strings formatter including for-loop or if conditions
https://stackoverflow.com/a/54734702/5745962
But I found no comment explaining why this happens
The looping construct you're using is a generator expression. To write one as a stand-alone expression, you need to add parentheses around it:
genexp = (f"{s}" for s in ["bar"])
If the generator expression is the only argument to a function, you don't need double parentheses (but you do if there are other separate arguments). Contrast:
s = sum(i % 2 for i in some_sequence) # count of odd elements, no extra parentheses needed
vs:
print(*(i for i in some_sequence if i % 2), sep=",") # print odds, parens are needed this time
There's nothing special about f-string used in the generator expression in your code, any expression works the same way.
These are examples of generator expressions and don't necessarily have anything specific to f-strings or which functions you use with them.
e.g.
>>> x = [1, 2, 3, 4]
>>> sum(i%2==0 for i in x)
2
The example counts the number of even integers in the list.
You can read more about them here: https://dbader.org/blog/python-generator-expressions
The f-string has nothing to do with it.
Although a generator expression generally requires parentheses:
some_gen = (f"{s}" for s in ["bar"])
print(foo(some_gen))
the parentheses can be omitted when the generator expression is the only argument to a function call:
# These two calls are equivalent.
foo((f"{s}" for s in ["bar"]))
foo( f"{s}" for s in ["bar"] )

Passing Variables in Function and compare each?

I'm trying to practice Haskell returns and datatypes. I'm trying to pass the following information into the program:
worm = 1:2:3:worm
eel = [1,2,3,1,2,3,1,2,3]
snake = 3:2:1:snake
whale = [1..100]
And i want to create a function that has a switch function to get the data and match it to its definition. For example, in Python:
def compare(str): #for one case and using string to clarify
if str == "1:2:3:worm":
return "worm"
I know the datatypes are lists but causes a lot of confusion. My code is giving me an error of Could not deduce (Num Char) Arising from use of worm
My code:
which :: [a] -> String
which x | x == [1,2,3,1,2,3,1,2,3] = "worm" | x == 3:2:1:snake = "snake" | otherwise = "F"
Is there another approach i'm missing? and why is my function giving me that error?
Two problems:
You can't have a function that returns a list of numbers sometimes and a string other times. That's literally the entire point of a strongly typed language. If you want something like that, you need to use a sum type.
You can't compare infinite lists. You can try, but your program will never finish.

Sympy solver bug in a for loop?

So I'm playing with Sympy in an effort to build a generic solver/generator of physics problems. One component is that I'm going for a function that will take kwargs and, according to what it got, rearrange the equation and substitute values in it. Thanks to SO, I managed to find the things I need for that.
However..... I've tried putting sympy.solve in a for loop to generate all those expressions and I've ran into.... something.
import sympy
R, U, I, eq = sympy.symbols('R U I eq')
eq = R - U/I
for x in 'RUI':
print(x)
print(sympy.solve(eq, x))
The output?
R
[U/I]
U
[I*R]
I
[]
However, whenever I do sympy.solve(eq, I) it works and returns [U/R].
Now, I'm guessing the issue is with sympy using I for imaginary unit and with variable hiding in blocks, but even when I transfer the symbol declaration inside the for loop (and equation as well), I still get the same problem.
I'm not sure I'll need this badly in the end, but this is interesting to say the least.
It's more like an undocumented feature than a bug. The loop for x in 'RUI' is equivalent to for x in ['R', 'U', 'I'], meaning that x runs over one-character strings, not sympy symbols. Insert print(type(x)) in the loop to see this. And note that sympy.solve(eq, 'I') returns [].
The loop for x in [R, U, I] solves correctly for each variable. This is the right way to write this loop.
The surprising thing is that you get anything at all when passing a string as the second argument of solve. Sympy documentation does not list strings among acceptable arguments. Apparently, it tries to coerce the string to a sympy object and does not always guess your meaning correctly: works with sympy.solve(eq, 'R') but not with sympy.solve(eq, 'I')
The issue is that some sympy functions "accidentally" work with strings as input because they call sympify on their input. But sympify('I') gives the imaginary unit (sqrt(-1)), not Symbol('I').
You should always define your symbols explicitly like
R, U, I = symbols("R U I")
and use those instead of strings.
See https://github.com/sympy/sympy/wiki/Idioms-and-Antipatterns#strings-as-input for more information on why you should avoid using strings with SymPy.

Haskell: Need Enlightenment with Calculator program

I have an assignment which is to create a calculator program in Haskell. For example, users will be able to use the calculator by command lines like:
>var cola =5; //define a random variable
>cola*2+1;
(print 11)
>var pepsi = 10
>coca > pepsi;
(print false)
>def coke(x,y) = x+y; //define a random function
>coke(cola,pepsi);
(print 15)
//and actually it's more complicated than above
I have no clue how to program this in Haskell. All I can think of right now is to read the command line as a String, parse it into an array of tokens. Maybe go through the array, detect keywords such "var", "def" then call functions var, def which store variables/functions in a List or something like that. But then how do I store data so that I can use them later in my computation?
Also am I on the right track because I am actually very confused what to do next? :(
*In addition, I am not allowed to use Parsec!*
It looks like you have two distinct kinds of input: declarations (creating new variables and functions) and expressions (calculating things).
You should first define some data structures so you can work out what sort of things you are going to be dealing with. Something like:
data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]
To start off with, just parse (tokenise and then parse the tokens, perhaps) the stuff into a Command, and then decide what to do with it.
Expressions are comparatively easy. You assume you already have all the definitions you need (an Environment) and then just look up any variables or do additions or whatever.
Definitions are a bit trickier. Once you've decided what new definition to make, you need to add it to the environment. How exactly you do this depends on how exactly you iterate through the lines, but you'll need to pass the new environment back from the interpreter to the thing which fetches the next line and runs the interpreter on it. Something like:
main :: IO ()
main = mainLoop emptyEnv
where
emptyEnv = []
mainLoop :: Environment -> IO ()
mainLoop env = do
str <- getLine
case parseCommnad str of
Nothing -> do
putStrLn "parse failed!"
mainLoop env
Just Quit -> do
return ()
Just (Define d) -> do
mainLoop (d : env)
Just (Calculate e) -> do
putStrLn (calc env e)
mainLoop env
-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type
calc will need to look stuff up in the environment you create as you go along, so you'll probably also need a function for finding which Definition corresponds to a given Name (or complaining that there isn't one).
Some other decisions you should make:
What do I do when someone tries to redefine a variable?
What if I used one of those variables in the definition of a function? Do I evaluate a function definition when it is created or when it is used?
These questions may affect the design of the above program, but I'll leave it up to you to work out how.
First, you can learn a lot from this tutorial for haskell programming
You need to write your function in another doc with .hs
And you can load the file from you compiler and use all the function you create
For example
plus :: Int -> Int -- that mean the function just work with a number of type int and return Int
plus x y = x + y -- they receive x and y and do the operation

Resources