Algorithms like min don't flatten all the way
To restore previous behaviour one can use `min (flat x)`
This commit is contained in:
parent
eb822a4a6e
commit
ab0ba8d4c8
@ -833,14 +833,15 @@ struct Value
|
|||||||
/// Using Explicit_Bool to prevent from implicit casts
|
/// Using Explicit_Bool to prevent from implicit casts
|
||||||
static Value from(Explicit_Bool b);
|
static Value from(Explicit_Bool b);
|
||||||
|
|
||||||
static Value from(Number n); ///< Create value of type number holding provided number
|
static Value from(Array &&array); ///< Create value of type array holding provided array
|
||||||
static Value from(std::string s); ///< Create value of type symbol holding provided symbol
|
static Value from(Block &&l); ///< Create value of type block holding provided block
|
||||||
static Value from(std::string_view s); ///< Create value of type symbol holding provided symbol
|
static Value from(Chord chord); ///< Create value of type music holding provided chord
|
||||||
static Value from(char const* s); ///< Create value of type symbol holding provided symbol
|
static Value from(Note n); ///< Create value of type music holding provided note
|
||||||
static Value from(Block &&l); ///< Create value of type block holding provided block
|
static Value from(Number n); ///< Create value of type number holding provided number
|
||||||
static Value from(Array &&array); ///< Create value of type array holding provided array
|
static Value from(char const* s); ///< Create value of type symbol holding provided symbol
|
||||||
static Value from(Note n); ///< Create value of type music holding provided note
|
static Value from(std::string s); ///< Create value of type symbol holding provided symbol
|
||||||
static Value from(Chord chord); ///< Create value of type music holding provided chord
|
static Value from(std::string_view s); ///< Create value of type symbol holding provided symbol
|
||||||
|
static Value from(std::vector<Value> &&array); ///< Create value of type array holding provided array
|
||||||
|
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
@ -1094,4 +1095,8 @@ static constexpr bool is_callable(Value::Type type)
|
|||||||
return type == Value::Type::Block || type == Value::Type::Intrinsic;
|
return type == Value::Type::Block || type == Value::Type::Intrinsic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flattens one layer: `[[[1], 2], 3]` becomes `[[1], 2, 3]`
|
||||||
|
Result<std::vector<Value>> flatten(Interpreter &i, std::span<Value>);
|
||||||
|
Result<std::vector<Value>> flatten(Interpreter &i, std::vector<Value>);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,6 +111,7 @@ static Result<Array> into_flat_array(Interpreter &i, std::vector<Value> args)
|
|||||||
return into_flat_array(i, std::span(args));
|
return into_flat_array(i, std::span(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Helper to convert method to it's name
|
/// Helper to convert method to it's name
|
||||||
template<auto> struct Number_Method_Name;
|
template<auto> struct Number_Method_Name;
|
||||||
template<> struct Number_Method_Name<&Number::floor> { static constexpr auto value = "floor"; };
|
template<> struct Number_Method_Name<&Number::floor> { static constexpr auto value = "floor"; };
|
||||||
@ -466,8 +467,8 @@ static Result<Value> builtin_update(Interpreter &i, std::vector<Value> args)
|
|||||||
|
|
||||||
if (Lazy_And_Number::typecheck_front(args)) {
|
if (Lazy_And_Number::typecheck_front(args)) {
|
||||||
auto [v, index] = Lazy_And_Number::move_from(args);
|
auto [v, index] = Lazy_And_Number::move_from(args);
|
||||||
auto array = Try(into_flat_array(i, { Value::from(std::move(v)) }));
|
auto array = Try(flatten(i, { Value::from(std::move(v)) }));
|
||||||
array.elements[index.as_int()] = std::move(args.back());
|
array[index.as_int()] = std::move(args.back());
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,41 +501,41 @@ static Result<Value> builtin_flat(Interpreter &i, std::vector<Value> args)
|
|||||||
static Result<Value> builtin_shuffle(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_shuffle(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
static std::mt19937 rnd{std::random_device{}()};
|
static std::mt19937 rnd{std::random_device{}()};
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::shuffle(array.elements.begin(), array.elements.end(), rnd);
|
std::shuffle(array.begin(), array.end(), rnd);
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Permute arguments
|
/// Permute arguments
|
||||||
static Result<Value> builtin_permute(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_permute(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::next_permutation(array.elements.begin(), array.elements.end());
|
std::next_permutation(array.begin(), array.end());
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sort arguments
|
/// Sort arguments
|
||||||
static Result<Value> builtin_sort(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_sort(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::sort(array.elements.begin(), array.elements.end());
|
std::sort(array.begin(), array.end());
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reverse arguments
|
/// Reverse arguments
|
||||||
static Result<Value> builtin_reverse(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_reverse(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
std::reverse(array.elements.begin(), array.elements.end());
|
std::reverse(array.begin(), array.end());
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get minimum of arguments
|
/// Get minimum of arguments
|
||||||
static Result<Value> builtin_min(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_min(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
auto min = std::min_element(array.elements.begin(), array.elements.end());
|
auto min = std::min_element(array.begin(), array.end());
|
||||||
if (min == array.elements.end())
|
if (min == array.end())
|
||||||
return Value{};
|
return Value{};
|
||||||
return *min;
|
return *min;
|
||||||
}
|
}
|
||||||
@ -542,9 +543,9 @@ static Result<Value> builtin_min(Interpreter &i, std::vector<Value> args)
|
|||||||
/// Get maximum of arguments
|
/// Get maximum of arguments
|
||||||
static Result<Value> builtin_max(Interpreter &i, std::vector<Value> args)
|
static Result<Value> builtin_max(Interpreter &i, std::vector<Value> args)
|
||||||
{
|
{
|
||||||
auto array = Try(into_flat_array(i, std::move(args)));
|
auto array = Try(flatten(i, std::move(args)));
|
||||||
auto max = std::max_element(array.elements.begin(), array.elements.end());
|
auto max = std::max_element(array.begin(), array.end());
|
||||||
if (max == array.elements.end())
|
if (max == array.end())
|
||||||
return Value{};
|
return Value{};
|
||||||
return *max;
|
return *max;
|
||||||
}
|
}
|
||||||
@ -563,10 +564,10 @@ static Result<Value> builtin_partition(Interpreter &i, std::vector<Value> args)
|
|||||||
|
|
||||||
auto predicate = std::move(args.front());
|
auto predicate = std::move(args.front());
|
||||||
Try(guard(is_callable, predicate));
|
Try(guard(is_callable, predicate));
|
||||||
auto array = Try(into_flat_array(i, std::span(args).subspan(1)));
|
auto array = Try(flatten(i, std::span(args).subspan(1)));
|
||||||
|
|
||||||
Array tuple[2] = {};
|
Array tuple[2] = {};
|
||||||
for (auto &value : array.elements) {
|
for (auto &value : array) {
|
||||||
tuple[Try(predicate(i, { std::move(value) })).truthy()].elements.push_back(std::move(value));
|
tuple[Try(predicate(i, { std::move(value) })).truthy()].elements.push_back(std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,13 +590,13 @@ static Result<Value> builtin_rotate(Interpreter &i, std::vector<Value> args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto offset = std::move(args.front()).n.as_int();
|
auto offset = std::move(args.front()).n.as_int();
|
||||||
auto array = Try(into_flat_array(i, std::span(args).subspan(1)));
|
auto array = Try(flatten(i, std::span(args).subspan(1)));
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
offset = offset % array.elements.size();
|
offset = offset % array.size();
|
||||||
std::rotate(array.elements.begin(), array.elements.begin() + offset, array.elements.end());
|
std::rotate(array.begin(), array.begin() + offset, array.end());
|
||||||
} else if (offset < 0) {
|
} else if (offset < 0) {
|
||||||
offset = -offset % array.elements.size();
|
offset = -offset % array.size();
|
||||||
std::rotate(array.elements.rbegin(), array.elements.rbegin() + offset, array.elements.rend());
|
std::rotate(array.rbegin(), array.rbegin() + offset, array.rend());
|
||||||
}
|
}
|
||||||
return Value::from(std::move(array));
|
return Value::from(std::move(array));
|
||||||
}
|
}
|
||||||
|
28
src/value.cc
28
src/value.cc
@ -130,6 +130,14 @@ Value Value::from(Array &&array)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value Value::from(std::vector<Value> &&array)
|
||||||
|
{
|
||||||
|
Value v;
|
||||||
|
v.type = Type::Array;
|
||||||
|
v.array = Array { .elements = std::move(array) };
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
Value Value::from(Note n)
|
Value Value::from(Note n)
|
||||||
{
|
{
|
||||||
Value v;
|
Value v;
|
||||||
@ -494,3 +502,23 @@ std::ostream& operator<<(std::ostream& os, Chord const& chord)
|
|||||||
}
|
}
|
||||||
return os << ']';
|
return os << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<std::vector<Value>> flatten(Interpreter &interpreter, std::span<Value> args)
|
||||||
|
{
|
||||||
|
std::vector<Value> result;
|
||||||
|
for (auto &x : args) {
|
||||||
|
if (is_indexable(x.type)) {
|
||||||
|
for (usize i = 0; i < x.size(); ++i) {
|
||||||
|
result.push_back(Try(x.index(interpreter, i)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.push_back(std::move(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<std::vector<Value>> flatten(Interpreter &i, std::vector<Value> args)
|
||||||
|
{
|
||||||
|
return flatten(i, std::span(args));
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user