I'm trying to implement the classic higher order range zipWith as follows
import std.traits: allSatisfy;
import std.range: isInputRange;
auto zipWith(fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges))
{
import std.range: zip;
return zip(ranges).map!fun;
}
but the
unittest
{
auto x = [1, 2, 3, 4, 5];
zipWith!((a, b) => a + b)(x, x);
}
fails with error
template algorithm_ex.zipWith cannot deduce function from argument types !((a, b) => a + b)(int[], int[]), candidates are: (d-dmd-unittest)
algorithm_ex.zipWith(fun, Ranges...)(Ranges ranges) if (Ranges.length && allSatisfy!(isInputRange, Ranges))
and I don't understand why. Clues anyone?
Update:
After CyberShadows nice answer I now have
import std.traits: allSatisfy;
/** Zip $(D ranges) together with operation $(D fun).
TODO: Simplify when Issue 8715 is fixed providing zipWith
*/
auto zipWith(alias fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges)) {
import std.range: zip;
import std.algorithm: map;
import std.functional: binaryFun;
static if (ranges.length == 2)
return zip(ranges).map!(a => binaryFun!fun(a.expand));
else if (ranges.length >= 3)
return zip(ranges).map!(a => naryFun(a.expand));
else
static assert(false, "Need at least 2 range arguments.");
}
unittest {
auto x = [1, 2, 3];
import std.array: array;
assert(zipWith!"a+b"(x, x).array == [2, 4, 6]);
assert(zipWith!((a, b) => a + b)(x, x).array == [2, 4, 6]);
assert(zipWith!"a+b+c"(x, x, x).array == [3, 6, 9]);
}
Is it possible to extend it to support nary fun's via strings, like zipWith!"a+b+c"(x,x,x)? I ask especially because I notice that there is code for naryFun in std.functional but it's commented out.
You must declare the fun template parameter as an alias parameter, otherwise it is declared as a type parameter:
auto zipWith(alias fun, Ranges...)( // ...
You need to import std.algorithm for map.
std.range.zip will return a range of std.typecons.Tuple, which will not automatically expand into your lambda's two parameters. You need to expand the tuple explicitly.
Fixed code:
import std.traits: allSatisfy;
import std.range: isInputRange;
import std.algorithm: map;
auto zipWith(alias fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges))
{
import std.range: zip;
return zip(ranges).map!(t => fun(t.expand));
}
unittest
{
auto x = [1, 2, 3, 4, 5];
zipWith!((a, b) => a + b)(x, x);
}
Is it possible to extend it to support nary fun's via strings, like zipWith!"a+b+c"(x,x,x)?
I don't see why not:
import std.string;
private string genNaryFun(string fun, V...)()
{
string code;
foreach (n, v; V)
code ~= "alias values[%d] %s;".format(n, cast(char)('a'+n));
code ~= "return " ~ fun ~ ";";
return code;
}
template naryFun(string fun)
{
auto naryFun(V...)(V values)
{
mixin(genNaryFun!(fun, V));
}
}
unittest
{
alias naryFun!"a + b + c" test;
assert(test(1, 2, 3) == 6);
}
Related
I want to write a module that can optionally combine its children as either a union or a difference.
module u_or_d(option="d") {
if (option == "d") {
difference() children();
} else {
union() children();
}
}
module thing(option) {
u_or_d(option) {
cube(10, center=true);
cylinder(h=20, d=5, center=true);
}
}
translate([-15, 0, 0]) thing("d");
translate([ 15, 0, 0]) thing("u");
I was surprised that this doesn't work. Both instances of thing appear to create a union of the cube and the cylinder.
The CSG Tree Dump shows the problem. Here's the relevant excerpt:
difference() {
group() {
cube(size = [10, 10, 10], center = true);
cylinder($fn = 0, $fa = 12, $fs = 2, h = 20, r1 = 2.5, r2 = 2.5, center = true);
}
}
The children are wrapped in a group, so the difference() effectively has only one child, which happens to be an implicit union of the wrapped children.
Is there a way to invoke children() that avoids this unwanted grouping? If not, is there another way for a module to allow the invoker to select how the module combines its children?
I found a solution:
module u_or_d(option="d") {
if (option == "d" && $children > 1) {
difference() {
children([0]);
children([1:$children-1]);
}
} else {
union() children();
}
}
You still get a group wrapped around each invocation of children, but at least we can make two groups.
I have a simple class definition:
class State {
private:
Eigen::Vector3f m_data;
public:
State(const Eigen::Vector3f& state) : m_data(state) { }
Eigen::Vector3f get() const { return m_data; }
void set(const Eigen::Vector3f& _state) { m_data = _state; }
std::string repr() const {
return "state data: [x=" + std::to_string(m_data[0]) + ", y=" + std::to_string(m_data[1]) + ", theta=" + std::to_string(m_data[2]) + "]";
}
};
I then expose the above in python with pybind11:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &_State::get)
.def("set", &_State::set)
.def("__repr__", &_State::repr);
}
And everything works fine; I am able to import this module into python and construct a State instance with a numpy array. This isn't exactly what I want though. I want to be able to access this object as if it were a numpy array; I want to be able to do something like the following in python:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a[0])
(the above throws a TypeError: 'bound_state.State' object does not support indexing)
In the past, I've used boost::python to expose lists by using add_property and this allowed indexing of the underlying data in C++. does pybind11 have something similar that can work with Eigen? Could someone provide an example showing how to expose a State instance that is indexable?
Per the API Docs, this can be done easily with the def_property method.
Turn this bit:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &State::get)
.def("set", &State::set)
.def("__repr__", &State::repr);
}
Into this:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def_property("m_data", &State::get, &State::set)
.def("__repr__", &State::repr);
}
Now, from the python-side, I can do:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a.m_data[0])
This is not exactly what I want, but is a step in the right direction.
Is it possible to create a macro which counts the number of expanded items?
macro_rules! count {
($($name:ident),*) => {
pub enum Count {
$(
$name = 1 << $i // $i is the current expansion index
),*
}
}
}
count!(A, B, C);
Here is a macro that counts the number of matched items:
macro_rules! count_items {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_items!($($rest),*)
}
}
fn main() {
const X: usize = count_items!(a);
const Y: usize = count_items!(a, b);
const Z: usize = count_items!(a, b, c);
assert_eq!(1, X);
assert_eq!(2, Y);
assert_eq!(3, Z);
}
Note that the counting is computed at compile time.
For your example, you can do it using accumulation:
macro_rules! count {
($first:ident, $($rest:ident),*) => (
count!($($rest),+ ; 0; $first = 0)
);
($cur:ident, $($rest:ident),* ; $last_index: expr ; $($var:ident = $index:expr)+) => (
count!($($rest),* ; $last_index + 1; $($var = $index)* $cur = $last_index + 1)
);
($cur:ident; $last_index:expr ; $($var:ident = $index:expr)+) => (
#[repr(C)]
enum Count {
$($var = 1 << $index),*,
$cur = 1 << ($last_index + 1),
}
);
}
pub fn main() {
count!(A, B, C, D);
assert_eq!(1, Count::A as usize);
assert_eq!(2, Count::B as usize);
assert_eq!(4, Count::C as usize);
assert_eq!(8, Count::D as usize);
}
Yes, if you pack it as array of idents:
macro_rules! count {
($($name:ident),*) => {
{
let counter = [$(stringify!($name),)*];
counter.len()
}
}
}
Count, names, reverse order of names are available. After, you can use it to construct something. For enum building you have to join it with something like this.
In this context, no. A macro could create an expression that counts the number of identifiers passed to it, but it would only be evaluated at runtime. I created this example in just a few minutes, but I realized it would not work for what you're doing.
Compiler plugins, however, are particularly suited to this sort of work. While they're not trivial to implement, I don't think it would be overly difficult to create one for this purpose. Maybe take a look, try your hand at it, and come back if you get stuck?
Since this question is general, posting an example of counting where arguments are separated by white-space (not commas).
Although in retrospect it seems obvious, it took me a while to figure out:
/// Separated by white-space.
#[macro_export]
macro_rules! count_args_space {
($name:ident) => { 1 };
($first:ident $($rest:ident) *) => {
1 + count_args_space!($($rest) *)
}
}
/// Separated by commas.
#[macro_export]
macro_rules! count_args_comma {
($name:ident) => { 1 };
($first:ident, $($rest:ident),*) => {
1 + count_args_comma!($($rest),*)
}
}
Second example is from #malbarbo, just posting to so you can see the 2x changes that were needed.
Looking to convert Java Swing DatePicker into Scala but facing difficulty in one area of the code. How should I probably translate the if (x > 6) part into scala?
Original Java taken from http://www.roseindia.net/tutorial/java/swing/datePicker.html
for (int x = 0; x < button.length; x++) {
final int selection = x;
button[x] = new JButton();
button[x].setFocusPainted(false);
button[x].setBackground(Color.white);
if (x > 6)
button[x].addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
day = button[selection].getActionCommand();
d.dispose();
}
});
if (x < 7) {
button[x].setText(header[x]);
button[x].setForeground(Color.red);
}
p1.add(button[x]);
}
Converted Scala
for (x <- 0 until buttons.length) {
val selection = x
buttons(x) = new Button {
focusPainted = false
background = Color.white
}
if (x > 6)
buttons(x).reactions += {
case ButtonClicked(_) => {
day = buttons(selection).action
d.dispose()
}
}
if (x < 7) {
buttons(x).text = header(x)
buttons(x).foreground = Color.red
}
contents += buttons(x)
}
What is wrong with your translation? Is it not working? The only thing I can see at a glance is that you do not listen to the button:
button(x) listenTo button(x)
But I'm not sure how wise a button listening to itself is, or whether there are any nasty consequences. You don't need to add the reactions to the button itself, you could probably add them to the date picker itself.
Also, something like zipWithIndex is possibly preferable to the way you have done it:
buttons.zipWithIndex foreach { case (button, x) =>
//no need to use buttons(x)
}
The if(x < 7) could be replaced by else, that would be clearer.
You could use a match statement as well:
x match {
case xx if xx > 6 => ...
case _ => ...
}
I am new to python, I have looked at boost python, and it looks very
impressive. However going through the introduction I can not find
any examples where, vector of objects are returned as python list/tuples.
i.e Take this example, I want to expose class X, Cont and all its functions.
critical bit being return a vector of X's or strings to python
class X {};
class Cont {
.....
// how can this be exposed using boost python
const std::vector<X>& const_ref_x_vec() const { return x_vec_;}
std::vector<X> value_x_vec() const { return x_vec;}
const std::vector<std::string>& const_ref_str_vec() const { return str_vec_;}
std::vector<std::string> value_str_vec() const { return str_vec_; }
...
private:
std::vector<X> x_vec_;
std::vector<std::string> str_vec_;
};
My own fruitless attempt at trying to expose the functions like
const_ref_x_vec(), value_x_vec(),etc just leads to compile errors.
from googling around I have not seen any example that support returning vectors
by value or reference. Is this even possible with boost python?
are there any workarounds ? should I be using SWIG for this case ?
Any help appreciated.
Avtar
Autopulated's reason was essentially correct, but the code was more complicated then necessary.
The vector_indexing_suite can do all that work for you:
class_< std::vector<X> >("VectorOfX")
.def(vector_indexing_suite< std::vector<X> >() )
;
There is a map_indexing_suite as well.
Because you can't expose template types to python you have to explicitly expose each sort of vector that you want to use, for example this is from my code:
Generic template to wrap things:
namespace bp = boost::python;
inline void IndexError(){
PyErr_SetString(PyExc_IndexError, "Index out of range");
bp::throw_error_already_set();
}
template<class T>
struct vec_item{
typedef typename T::value_type V;
static V& get(T& x, int i){
static V nothing;
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) return x[i];
IndexError();
return nothing;
}
static void set(T& x, int i, V const& v){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x[i] = v;
else IndexError();
}
static void del(T& x, int i){
if(i < 0) i += x.size();
if(i >= 0 && i < int(x.size())) x.erase(x.begin() + i);
else IndexError();
}
static void add(T& x, V const& v){
x.push_back(v);
}
};
Then, for each container:
// STL Vectors:
// LineVec
bp::class_< std::vector< Line > >("LineVec")
.def("__len__", &std::vector< Line >::size)
.def("clear", &std::vector< Line >::clear)
.def("append", &vec_item< std::vector< Line > >::add,
bp::with_custodian_and_ward<1, 2>()) // let container keep value
.def("__getitem__", &vec_item< std::vector< Line > >::get,
bp::return_value_policy<bp::copy_non_const_reference>())
.def("__setitem__", &vec_item< std::vector< Line > >::set,
bp::with_custodian_and_ward<1,2>()) // to let container keep value
.def("__delitem__", &vec_item< std::vector< Line > >::del)
.def("__iter__", bp::iterator< std::vector< Line > >())
;
// ...
A similar approach is possible for std::map.
I used lots of help from wiki.python.org when writing this.