I am trying to call a function from a python file I wrote in SML. I am receiving a tycon mismatch error and I don't understand why. This is my SML code
fun interpreter(inFile: string, outFile: string)=
let
val s = interpreter(inFile, outFile)
in
OS.Process.system ("python interpreter.py" ^ s)
end;
And this is the error I am receiving
- use "in.sml";
[opening in.sml]
in.sml:1.6-6.6 Error: right-hand-side of clause doesn't agree with function result type [tycon mismatch]
expression: ?.OS_Process.status
result type: string
in declaration:
interpreter =
(fn (<pat> : string,<pat> : string) =>
let val <binding> in OS.Process.system <exp> end)
val it = () : unit
This is the method in python I am trying to call:
def interpreter(input, output):
x = Interpreter()
x.interpreter(input, output)
The compiler is trying to reconcile the result/return type of interpreter which you are calling recursively here: val s = interpreter(inFile, outFile). the compiler thinks s must be of type string since you are concatenating it with ^ but the body of the function you are returning the value returned by OS.Process.system ("python interpreter.py" ^ s) which must be ?.OS_Process.status.
Related
I'd like to write a Snowflake scalar UDF in Python which takes a variable number of string arguments.
The idea I had was to use array type for this (i.e. array can handle variable number of elements) but the issue I had with this was that as soon as a single element of array argument was NULL, Snowflake threw an error and I need to be able to handle these NULLs.
Code:
create or replace function udx_py_uuid5_null(a array)
returns string
language python
runtime_version = 3.8
handler = 'f_uuid5'
as $$
import uuid
from typing import List, Optional
_null_uuid = uuid.UUID('00000000-0000-0000-0000-000000000000')
def f_uuid5(args: List[Optional[str]]):
args = [arg if not getattr(arg, "is_sql_null", False) else '' for arg in args]
return str(uuid.uuid5(_null_uuid, ':'.join(args)))
$$;
I'm trying to handle NULLs as described here but it seems to me as if this only applies to "first-level" arguments. As shown in the solution, desired behaviour is to replace NULLs with empty string before calculating the UUID.
Call:
select udx_py_uuid5_null([NULL, 'test', 'test1', NULL]);
Error message:
Python Interpreter Error: Traceback (most recent call last): File "_udf_code.py", line 7, in f_uuid5 TypeError: sequence item 0: expected str instance, NoneType found in function UDX_PY_UUID5_NULL with handler f_uuid5
Instead of trying to replacing NULLs with empty string why not simply remove None values:
args = [arg if not getattr(arg, "is_sql_null", False) else '' for arg in args]
=>
args = list(filter(lambda arg: arg is not None, args))
Full code:
create or replace function udx_py_uuid5_null(a array)
returns string
language python
runtime_version = 3.8
handler = 'f_uuid5'
as $$
import uuid
from typing import List, Optional
_null_uuid = uuid.UUID('00000000-0000-0000-0000-000000000000')
def f_uuid5(args: List[Optional[str]]):
args = list(filter(lambda arg: arg is not None, args))
return str(uuid.uuid5(_null_uuid, ':'.join(args)))
$$;
select udx_py_uuid5_null([NULL, 'test', 'test1', NULL]);
Output:
I defined the _exec_ function for getting the output of a function represented by a string.
For instance the sgn function evaluated with the arg value (see code below).
Then I will have to perform a single eval in the end.
(Warning: exec or eval of unknown code must be secured before use.)
def _exec_(thecode):
local = {}
exec(thecode, globals(), local)
return local["_output_"]
sgn = "\nif _input_[0]<0:\n _output_ = -1\nif _input_[0]==0:\n _output_ = 0\nif _input_[0]>0:\n _output_ = 1"
arg = "[5]"
code_list = ["_input_ = "+arg+sgn]
print(eval("1+_exec_(code_list[0])"))
The last 2 lines provide the good result.
However I will have to use it for an undetermined number of times with various "string-functions" and "string-arguments".
Is it possible to do it with only 1 named string instead of a list of strings?
I tried:
code = "1+_exec_(_input_ = "+arg+sgn+")"
print(eval(code))
which lead to SyntaxError: invalid syntax.
Maybe the encoding of special characters is wrong, then I tried:
code = "1+_exec_(_input_ = "+arg+sgn.encode('unicode-escape').decode()+")"
print(eval(code))
which lead to SyntaxError: unexpected character after line continuation character.
I also tried to use the answer to Python: exec() a code block and eval() the last line, without success.
They aren't the same strings, "seemingly" or otherwise. Just take the eval out of both print(eval(...)) calls and compare:
>>> print("1+_exec_(code_list[0])")
1+_exec_(code_list[0])
vs:
>>> code = "1+_exec_(_input_ = "+arg+sgn+")"
>>> print(code)
1+_exec_(_input_ = [5]
if _input_[0]<0:
_output_ = -1
if _input_[0]==0:
_output_ = 0
if _input_[0]>0:
_output_ = 1)
That latter one doesn't look anything like something that might be expected to be valid syntax.
In most interpreted languages (example given in psuedo PHP) I would be able to do something like this
function f($name, &$errors = null) {
if(something_wrong) {
if(!is_null($errors) {
$errors[] = 'some error';
}
return false;
}
}
if(!f('test', $errs = array()) {
print_r($errs);
}
And get a result like
Array
(
[0] => some error
)
However when I try this in Python
def f(name, errors = None):
if something_wrong:
if errors:
errors.append('some error')
return False
if not f('test', errs = []):
print str(errs)
I get an error
TypeError: f() got an unexpected keyword argument 'errs'
Which makes perfect sense in the context of Python thinking I am trying to set a specific argument, and not create a new variable altogether.
However if I try
if not f('test', (errs = [])):
print str(errs)
I get
f('test', (errs = []))
^
SyntaxError: invalid syntax
Because I think now it assumes I am trying to create a tuple.
Is there any way to keep this code on one line, or do I absolutely have to initialise the variable on it's own before passing it to the function/method? From what I can tell the only solution is this
errs = []
if not f('test', errs):
print str(errs)
It should be called as f(name, errors = []) or f(name, []). If you want to init with attribute name, python requires the variable key you given is same with any attribute name you declared in the function definition.
"In Python, assignment is a statement, not an expression, and can
therefore not be used inside an arbitrary expression."
see http://effbot.org/pyfaq/why-can-t-i-use-an-assignment-in-an-expression.htm
I get to read a line from a file that contain certain set of numbers per line. My problem is that the input is from a string line and then I need to process it as integer, making the conversion as usually suggested. Although I check previous post on this problem, maybe because I am using structure and split can be the reason why the conversion is not working properly.
Here this error is popping up:
TypeError: not all arguments converted during string formatting
SyntaxError: invalid syntax
This is a snapshot from the code I have done so far:
class Data:
value1 = 0
max = 10
class Process:
value = None
def __init__(self):
self.input = Data()
def __del__(self):
self.input
def getValue(self,line):
counter=0
for word in line.split():
if counter == 0:
self.input.value1=(int)word
for number in self.input.max:
if (number % self.input.value1 ==0):
print(number)
def readingFile(self):
file = open(filename, "r")
for line in file:
self.getValue(line)
Any suggestion what might be missing? I am running on Linux Python 3 using command line to compile.
The invalid syntax comes from -
self.input.value1=(int)word
In python, the casting is not the same as in C/C++/Java , instead of using (datetype)variable you have to use datatype(variable) , though that is only for primitive datatypes. For other datatypes, you do not need casting, as python is a dynamically typed language.
You should use -
self.input.value1 = int(word)
EDIT:
For the new error the OP is getting -
{{ for number in self.input.max: }} >> TypeError: 'int' object is not iterable.
You cannot iterate over an int object, just as the error indicates, to me it looks like both self.input.value1 and self.input.max are single integers, so you may want to do -
if self.input.max % self.input.value1 == 0:
print(self.input.max)
I'm trying to convert a Ruby script into a Python script (having absolutely no understanding of the various functions in Ruby) and can't find anything on the Ruby sub function.
Here's the function I'm trying to translate:
def getCCache(arg1, arg2, arg3)
local4 = Digest::MD5.hexdigest(arg1 + arg2)
local5 = 0
while (local5 < arg3.length)
temp1 = arg3[local5]
temp2 = local5
local5 += local5;
local4.sub(temp1, arg3[temp2])
local5 += 1
end
return (local4)
end
The line I'm having trouble with is local4.sub(temp1, arg3[temp2]). What does the sub function do? If there's an equivalent in Python I would appreciate that as well.
local4.sub(temp1, arg3[temp2])
does nothing. It returns a copy of the string local4 with the first occurance of the substring referenced by temp1 substituted by the second argument. Then the result is discarded : no variable is assigned to the result.
local4 = local4.sub(temp1, arg3[temp2]) #or
local4.sub!(temp1, arg3[temp2])
would both do string substitution.
sub(pattern) {|...| block } → $_
Equivalent to $_.sub(args), except that $_ will be updated if substitution occurs. Available only when -p/-n command line option specified.
$_ is a ruby global variable and it represents string last read by gets