mypy pop error for 'None' object is not iterable - mypy

Here I have a function like this:
def func_A(delta: Optional[List[int]],
margin: Optional[List[int]]
mode: str = 'OUT') -> Tuple[int,
Optional[List[int]],
Optional[List[int]]]:
result = 1
if mode == "OUT":
return result, [1,2,3], [4,5,6]
elif mode == "IN":
delta_x, delta_y = delta
margin_x, margin_y = margin
return result, None, None
else:
raise ValueError('wrong key')
however, when i use the function like below, mypy will pop error:
result, delta_options, margin_options = func_A(delta=None,
margin=None,
mode="OUT")
gives error:
'None' object is not iterable
which part is wrong for my code? Thanks in advance.
P.S. my mypy configuration is below:
mypy --ignore-missing-imports --follow-imports=skip --strict-optional .

The problem is L.10
delta_x, delta_y = delta
The type of delta is Optional[List[int]]. So delta can be None. If delta is None, the code does not work.
delta_x, delta_y = None
So you need to handle delta is None case before the code.
e.g.
if delta is not None:
delta_x, delta_y = delta
or
delta_x, delta_y = delta if delta is not None else None, None
etc.

Related

How can I call a rust function from R that returns Vec<Vec<f64>>?

I have implemented a function for sampling from M different normal distributions N times in Rust because my R code was too slow. It is also parallelized. Here is the pure Rust code:
use rand_distr::{Normal, Distribution};
use rayon::prelude::*;
fn rust_rprednorm(n: i32, means: Vec<f64>, sds: Vec<f64>) -> Vec<Vec<f64>> {
let mut preds = vec![vec![0.0; n as usize]; means.len()];
preds.par_iter_mut().enumerate().for_each(|(i, e)| {
let mut rng = rand::thread_rng();
(0..n).into_iter().for_each(|j| {
let normal = Normal::new(means[i], sds[i]).unwrap();
e[j as usize] = normal.sample(&mut rng);
})
});
preds
}
Which I am trying to call from R using the rextendr library. The code is inside a utils.R file I import using source():
code <- r"(
use rand_distr::{Normal, Distribution};
use rayon::prelude::*;
#[extendr]
fn rust_rprednorm(n: i32, means: Vec<f64>, sds: Vec<f64>) -> Vec<Vec<f64>> {
let mut preds = vec![vec![0.0; n as usize]; means.len()];
preds.par_iter_mut().enumerate().for_each(|(i, e)| {
let mut rng = rand::thread_rng();
(0..n).into_iter().for_each(|j| {
let normal = Normal::new(means[i], sds[i]).unwrap();
e[j as usize] = normal.sample(&mut rng);
})
});
preds
}
)"
rust_source(code = code, dependencies = list(`rand` = "0.8.5", `rand_distr` ="0.4.3", `rayon` = "1.6.1"))
The error is:
Error in `invoke_cargo()`:
! Rust code could not be compiled successfully. Aborting.
✖ error[E0277]: the trait bound `Robj: From<Vec<Vec<f64>>>` is not satisfied
--> src\lib.rs:6:5
|
6 | #[extendr]
| ^^^^^^^^^^ the trait `From<Vec<Vec<f64>>>` is not implemented for `Robj`
|
= help: the following other types implement trait `From<T>`:
<Robj as From<&'a [T]>>
<Robj as From<&Altrep>>
<Robj as From<&Primitive>>
<Robj as From<&Robj>>
<Robj as From<&Vec<T>>>
<Robj as From<&extendr_api::Complexes>>
<Robj as From<&extendr_api::Doubles>>
<Robj as From<&extendr_api::Environment>>
and 71 others
= note: this error originates in the attribute macro `extendr` (in Nightly builds, run with -Z macro-backtrace for more info)
✖ error: aborting due to previous error
Traceback:
1. source("inla_predictive_distribution_utils.R")
2. withVisible(eval(ei, envir))
3. eval(ei, envir)
4. eval(ei, envir)
5. rust_source(code = code, dependencies = list(rand = "0.8.5",
. rand_distr = "0.4.3", rayon = "1.6.1"))
6. invoke_cargo(toolchain = toolchain, specific_target = specific_target,
. dir = dir, profile = profile, quiet = quiet, use_rtools = use_rtools)
7. check_cargo_output(compilation_result, message_buffer, tty_has_colors(),
. quiet)
8. ui_throw("Rust code could not be compiled successfully. Aborting.",
. error_messages, call = call, glue_open = "{<{", glue_close = "}>}")
9. withr::with_options(list(warning.length = message_limit_bytes),
. rlang::abort(message, class = "rextendr_error", call = call))
10. force(code)
11. rlang::abort(message, class = "rextendr_error", call = call)
12. signal_abort(cnd, .file)
I figured a nested vector would be supported since a regular vector is, but it appears not, do I need to implement this trait for Robj, or is there another way to go about it? I am also not sure if this is the recommended way to call Rust code from R.

How to make input[][] return a Just Int instead of String in Elm?

I'm a complete beginner to Elm an I'm struggling with types. I've been struggling a lot with types and I couldn't figure out a convenient way of fixing this problem. The piece of code in question is this:
view model =
div []
[ h1 [] [ text "Robot" ]
, input [ onInput SetX, value model.x ] []
, input [ onInput SetY, value model.y ] []
, input [ type_ "Int" , onInput SetCommands, value model.x] []
, button [ onClick ButtonPressed] []
, input [ readonly True ] []
]
X and Y are Ints used in the following function:
execute_orders : Int -> Int -> String -> String -> String -> { x : Int, y : Int, dir : String }
execute_orders x y commands lang dir =
let
moves =
case lang of
"English" ->
"RLF"
"French" ->
"HVG"
"Swedish" ->
"DGT"
_ ->
Debug.todo "No Language Found"
fw =
right 1 moves
directions =
facing dir
rght =
left 1 moves
lft =
slice 1 2 moves
first_move =
left 1 (toUpper commands)
rest =
slice 1 (length commands) (toUpper commands)
in
if first_move == "" then
{ x = x, y = y, dir = fromJust (head directions) }
else if first_move == fw then
if dir == "N" then
execute_orders x (y - 1) rest lang dir
else if dir == "E" then
execute_orders (x + 1) y rest lang dir
else if dir == "S" then
execute_orders x (y + 1) rest lang dir
else
execute_orders (x - 1) y rest lang dir
else if first_move == lft then
execute_orders x y rest lang (fromJust (head (turn_left directions)))
else if first_move == rght then
execute_orders x y rest lang (fromJust (head (turn_right directions)))
else
Debug.todo "branch '_' not implemented"
I need x and y to be Int's but casting them from String results in the Maybe Integer type...
There is no way to simply "cast" a String to an Int because there's no total mapping in that direction. There is, for example, no obvious integer representation for the string "banana". What you are struggling with isn't "types", but different things being different for different reasons, and having to make a decision to consolidate those differences.
String.toInt returns a Maybe Int because it's up to you to decide what to do when there's no reasonable and obvious integer representation for a given string. It's your choice whether you want to just default to 0, -1, or perhaps display the string - instead. These are all reasonable choices for different scenarios, but since String.toInt can't possibly know which scenario you're in, you have to make that decision.
If you simply want to fall back to a default integer, or you're certain that any given string will have a valid integer representation, you can use Maybe.withDefault:
String.toInt "42" |> Maybe.withDefault 0 -- 42
String.toInt "banana" |> Maybe.withDefault 0 -- 0
Or you can use a case expression to do something completely different:
case String.toInt s of
Just n ->
span [] [ text (n + 1 |> String.fromInt) ]
Nothing ->
button [ onClick ... ] [ text "-" ]
Since the HTML input event always deals with strings, you need to parse the string you receive at some point. There are three options that I see.
First, the payload of your event message can be a String, and then you parse that string in your update function.
type Msg
= SetX String
type alias Model =
{ x : Int }
update msg model =
case msg of
SetX xString ->
case String.toInt xString of
Nothing ->
model
Just x ->
{ model | x = x }
A variation of the above would be to store x as a Maybe String on your model if that makes sense, and/or storing some value for tracking an error state if you want to show a message when an invalid value is sent. This is the simplest and most flexible approach.
A second option is to have the payload of your event message be a Maybe Int. Html.Events.onInput is a function which takes a "tagger" function which accepts a String and outputs a message. While you can just give a message constructor that takes a String payload, you can also give a function which does some processing before creating a Msg value.
type Msg
= SetY (Maybe Int)
view model =
input [ type_ "number", onInput (\value -> String.toInt value |> SetY) ] []
The third option is to have the payload of your event message be an Int. This will require you to create your own version of onInput using Html.Events.on. on takes a Json.Decode.Decoder msg instead of the (String -> msg) function that onInput takes. The message will only be produced if the decoder succeeds; that is, events which produce a failed decoder will be ignored. This allows you to handle the case where the parsing fails within the event handler.
type Msg
= SetY Int
view model =
input [ type_ "number", onNumericInput SetY ] []
-- based on https://github.com/elm/html/blob/97f28cb847d816a6684bca3eba21e7dbd705ec4c/src/Html/Events.elm#L115-L122
onNumericInput : (Int -> msg) -> Attribute msg
onNumericInput toMsg =
let
alwaysStop : a -> ( a, Bool )
alwaysStop x =
( x, True )
failIfNothing : Maybe a -> Decode.Decoder a
failIfNothing maybe =
case maybe of
Nothing ->
Decode.fail "Parsing failed"
Just a ->
Decode.succeed a
decoder : Decode.Decoder msg
decoder =
Events.targetValue
|> Decode.map String.toInt
|> Decode.andThen failIfNothing
|> Decode.map toMsg
in
Events.stopPropagationOn "input" (decoder |> Decode.map alwaysStop)
You can see the last two options in a full example at https://ellie-app.com/h6fstFTyjXDa1

mypy: optional argument initialised to default value and used in lambda

I have a function of the form
def do_stuff(x: Optional[Dict[str, int]]=None)
if x is None:
x = {'foo': 1, 'bar': 2}
    # no type error
for k in x.keys():
a = x.get(k)
# type error
sorted(x.keys(), lambda k: x.get(k))
This raises a type error
Item "None" of "Optional[Dict[str, int]]" has no attribute "get"
On the sorted(x.keys() line. I assume this is because mypy hasn't realised that I've defined x in the if x is None: line so that it's no longer optional. This doesn't raise an error in the for k in x.keys(): .... x.get(k) form, only when the x.get(k) is in sorted (or perhaps in a lambda).
Is there some way to get around this?

Ocaml refs not retaining its value

(* junk.ml *)
let flag = ref false
let get_flag = !flag
let play_cards card =
Printf.printf "%s-clause\n" (if card >= 27 && card <= 39 then "true" else "false");
(flag := if card >= 27 && card <= 39 then true else !flag);
Printf.printf "check: %B " get_flag;
In utop, I imported junk.ml and received this output
val flag : bool ref = {contents = false} val get_flag : bool = false val play_cards : int -> unit = <fun>
I called play_cards 30;; and received this output:
true-clause
check: true - : unit = ()
However, when I called get_flag I received false. I was wondering if there is a concept of using refs that I misunderstood while writing this code.
Your variable get_flag is an immutable name for the value of !flag at the time it's defined. You shouldn't expect its value to change; OCaml variables have values that are immutable.
(Some values, like flag, are immutable names for things that themselves are mutable. In other words, flag is always going to be a name for the same reference, but the value stored in the reference, !flag, can change.)
Your comments indicate you want get_flag to have different values different times. One way to get this result is to define it as a function:
let get_flag () = !flag
Now you can call the function, and at each call it returns the value of flag at the moment of the call.
# let flag = ref false
let get_flag () = !flag;;
val flag : bool ref = {contents = false}
val get_flag : unit -> bool = <fun>
# get_flag ();;
- : bool = false
# flag := true;;
- : unit = ()
# get_flag ();;
- : bool = true
Your code doesn't make sense as shown, hearts_broken and get_hearts_broken are never defined. If, however, you have made these definitions somewhere else, then it is no wonder you see the result you're seeing, because play_cards doesn't actually modify flag, as you seem to assume.
I guess you have renamed hearts_broken to flag at some point, but forgot to fix play_cards? And that happened to not cause an error because you didn't restart the toplevel, so that the old definition was still around?

Which of these is pythonic? and Pythonic vs. Speed

I'm new to python and just wrote this module level function:
def _interval(patt):
""" Converts a string pattern of the form '1y 42d 14h56m'
to a timedelta object.
y - years (365 days), M - months (30 days), w - weeks, d - days,
h - hours, m - minutes, s - seconds"""
m = _re.findall(r'([+-]?\d*(?:\.\d+)?)([yMwdhms])', patt)
args = {'weeks': 0.0,
'days': 0.0,
'hours': 0.0,
'minutes': 0.0,
'seconds': 0.0}
for (n,q) in m:
if q=='y':
args['days'] += float(n)*365
elif q=='M':
args['days'] += float(n)*30
elif q=='w':
args['weeks'] += float(n)
elif q=='d':
args['days'] += float(n)
elif q=='h':
args['hours'] += float(n)
elif q=='m':
args['minutes'] += float(n)
elif q=='s':
args['seconds'] += float(n)
return _dt.timedelta(**args)
My issue is with the for loop here i.e the long if elif block, and was wondering if there is a more pythonic way of doing it.
So I re-wrote the function as:
def _interval2(patt):
m = _re.findall(r'([+-]?\d*(?:\.\d+)?)([yMwdhms])', patt)
args = {'weeks': 0.0,
'days': 0.0,
'hours': 0.0,
'minutes': 0.0,
'seconds': 0.0}
argsmap = {'y': ('days', lambda x: float(x)*365),
'M': ('days', lambda x: float(x)*30),
'w': ('weeks', lambda x: float(x)),
'd': ('days', lambda x: float(x)),
'h': ('hours', lambda x: float(x)),
'm': ('minutes', lambda x: float(x)),
's': ('seconds', lambda x: float(x))}
for (n,q) in m:
args[argsmap[q][0]] += argsmap[q][1](n)
return _dt.timedelta(**args)
I tested the execution times of both the codes using timeit module and found that the second one took about 5-6 seconds longer (for the default number of repeats).
So my question is:
1. Which code is considered more pythonic?
2. Is there still a more pythonic was of writing this function?
3. What about the trade-offs between pythonicity and other aspects (like speed in this case) of programming?
p.s. I kinda have an OCD for elegant code.
EDITED _interval2 after seeing this answer:
argsmap = {'y': ('days', 365),
'M': ('days', 30),
'w': ('weeks', 1),
'd': ('days', 1),
'h': ('hours', 1),
'm': ('minutes', 1),
's': ('seconds', 1)}
for (n,q) in m:
args[argsmap[q][0]] += float(n)*argsmap[q][1]
You seem to create a lot of lambdas every time you parse. You really don't need a lambda, just a multiplier. Try this:
def _factor_for(what):
if what == 'y': return 365
elif what == 'M': return 30
elif what in ('w', 'd', 'h', 's', 'm'): return 1
else raise ValueError("Invalid specifier %r" % what)
for (n,q) in m:
args[argsmap[q][0]] += _factor_for([q][1]) * n
Don't make _factor_for a method's local function or a method, though, to speed things up.
(I have not timed this, but) if you're going to use this function often it might be worth pre-compiling the regex expression.
Here's my take on your function:
re_timestr = re.compile("""
((?P<years>\d+)y)?\s*
((?P<months>\d+)M)?\s*
((?P<weeks>\d+)w)?\s*
((?P<days>\d+)d)?\s*
((?P<hours>\d+)h)?\s*
((?P<minutes>\d+)m)?\s*
((?P<seconds>\d+)s)?
""", re.VERBOSE)
def interval3(patt):
p = {}
match = re_timestr.match(patt)
if not match:
raise ValueError("invalid pattern : %s" % (patt))
for k,v in match.groupdict("0").iteritems():
p[k] = int(v) # cast string to int
p["days"] += p.pop("years") * 365 # convert years to days
p["days"] += p.pop("months") * 30 # convert months to days
return datetime.timedelta(**p)
update
From this question, it looks like precompiling regex patterns does not bring about noticeable performance improvement since Python caches and reuses them anyway. You only save the time it takes to check the cache which, unless you are repeating it numerous times, is negligible.
update2
As you quite rightly pointed out, this solution does not support interval3("1h 30s" + "2h 10m"). However, timedelta supports arithmetic operations which means one you can still express it as interval3("1h 30s") + interval3("2h 10m").
Also, as mentioned by some of the comments on the question, you may want to avoid supporting "years" and "months" in the inputs. There's a reason why timedelta does not support those arguments; it cannot be handled correctly (and incorrect code are almost never elegant).
Here's another version, this time with support for float, negative values, and some error checking.
re_timestr = re.compile("""
^\s*
((?P<weeks>[+-]?\d+(\.\d*)?)w)?\s*
((?P<days>[+-]?\d+(\.\d*)?)d)?\s*
((?P<hours>[+-]?\d+(\.\d*)?)h)?\s*
((?P<minutes>[+-]?\d+(\.\d*)?)m)?\s*
((?P<seconds>[+-]?\d+(\.\d*)?)s)?\s*
$
""", re.VERBOSE)
def interval4(patt):
p = {}
match = re_timestr.match(patt)
if not match:
raise ValueError("invalid pattern : %s" % (patt))
for k,v in match.groupdict("0").iteritems():
p[k] = float(v) # cast string to int
return datetime.timedelta(**p)
Example use cases:
>>> print interval4("1w 2d 3h4m") # basic use
9 days, 3:04:00
>>> print interval4("1w") - interval4("2d 3h 4m") # timedelta arithmetic
4 days, 20:56:00
>>> print interval4("0.3w -2.d +1.01h") # +ve and -ve floats
3:24:36
>>> print interval4("0.3x") # reject invalid input
Traceback (most recent call last):
File "date.py", line 19, in interval4
raise ValueError("invalid pattern : %s" % (patt))
ValueError: invalid pattern : 0.3x
>>> print interval4("1h 2w") # order matters
Traceback (most recent call last):
File "date.py", line 19, in interval4
raise ValueError("invalid pattern : %s" % (patt))
ValueError: invalid pattern : 1h 2w
Yes, there is. Use time.strptime instead:
Parse a string representing a time
according to a format. The return
value is a struct_time as returned
by gmtime() or localtime().

Resources