I remember I read about it somewhere in the docs and saw it being used in the code, but can't remember its name. It was described as "fancy way of doing array_merge()" or something. It allowed to merge two arrays with parameters and included some simple type checking.
function doSomething ($params) {
$defaultParams = [
'foo' => false,
'bar' => 1,
];
$p = whatsTheFunctionName($params, $defaultParams, [/* foo is bool, bar is int */]);
}
I think you're looking for the OptionsResolver component: "improved replacement for the array_replace PHP function".
See: https://symfony.com/doc/current/components/options_resolver.html
Related
Updated Question
I want to define a function named bsearch() to do binary searches against arrays of arbitrary object types. When I invoke the function, I want it to check whether or not the Type of the array contains a compare() method and use it, if it does. If it does not, I want it to fall back to using < and === (so it will work with strings and numbers).
What should the function declaration look like? (I don't need an actual implementation, just the syntax for a type-safe solution.)
Or maybe I'm going about this all wrong? How can I create a function that uses a method built into a parameter type if it exists, or use some other function when it doesn't?
Original Question
This is the original question, but I've replaced it with the above as it seems this wasn't getting my point across.
I want to define a function named bsearch() to do binary searches against arrays of arbitrary object types. So I'd like to do something like this:
type Comparator = <Type>(a: Type, b: Type) => -1 | 0 | 1;
static bsearch<Type extends { compare?: Comparator }>(
ary: Type[],
value: Type
): number { ... }
My goal is to specify that Type must extend a type that may or may not include the compare method. In my function, I will check whether the compare method exists on the value parameter and call if it does, or use a generic function (that uses < and ===) if it does not.
The definition of bsearch() does not produce any warnings or errors, but attempts to invoke it from my unit test does:
class Person {
name: string;
length: number;
compare: Comparator<Person>; // What goes here?
}
describe('Utils tests', () => {
const arrayOfInt = [10, 20, 30, 40];
const arrayOfStr = ['Alfred', 'Bob', 'Chuck'];
const arrayOfPersons: Person = [
{name:'Barney',length:2},
{name:'Fred',length:6}
{name:'Wilma',length:12},
];
it('can find integer in an array of integers', () => {
let search_for = 30;
let result = Utils.bsearch(arrayOfInt, search_for)
expect(result).to.be.equal(2);
});
it('can find string in an array of strings', () => {
let search_for = 'Bob';
let result = Utils.bsearch(arrayOfStr, search_for)
expect(result).to.be.equal(1);
});
it('can find Person in an array of Persons', () => {
// This one uses Person.compare() to do the search.
// The previous two tests used the fallback technique.
let search_for = {name:'Fred',length:6};
let result = Utils.bsearch(arrayOfPersons, search_for)
expect(result).to.be.equal(1);
});
});
The error message is:
TS2345: Argument of type 'number[]' is not assignable to parameter of type '{ compare?: Comparator | undefined; }[]'. Type 'number' has no properties in common with type '{ compare?: Comparator | undefined; }'.
I would appreciate pointers to other techniques if there is a better way to accomplish this (I'm still a TypeScript newbie).
Your generic is:
Type extends { compare?: Comparator }
Which means that Type must fulfill { compare?: Comparator } type. While passing object value, for example { name: 'Barney', length: 2, comparator: /* snip */}, is obviously correct, it's not the case for primitives like 10 and Bob. You need to include information about primitive types in the generic, for example:
Type extends ({ compare?: Comparator }) | number | string
Also, you'd probably want to enrich a bit the object typing:
{[key: string]: unknown, compare?: () => void } | number | string
Because, based on your description, you'd also want to accept also objects that do not have compare function in their type signature at all. If it does sound strange, I recommend reading about excess property checking.
I add a generic helper to find an item in an Array.
module.exports = function(array, findFunctionString) {
const fn = new Function("return" + findFunctionString)();
return array.find(fn)
};
My array is like :
[{label: "foo", selected: true}, {label: "bar", selected: false}]
What I'm looking now is to get the result and assign to a template variable with a specific key of this returned object.
{{#> myTemplate myVar=(find myArray "(el) => el.selected").label}}{{/myTemplate}}
I still got an error
Expecting 'CLOSE_RAW_BLOCK', 'CLOSE', 'CLOSE_UNESCAPED', 'OPEN_SEXPR', 'CLOSE_SEXPR', 'ID', 'OPEN_BLOCK_PARAMS', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', got 'SEP'
Yet, if remove ".label", no error, the object is well assigned to myVar. But I just want to assign the value of the key label.
Why can't I access to the key of the returned object ?
The solution was to use in addition lookup helper.
label=(lookup (find data.languageSelector.options "(el => el.selected)") "label")
A library presents me with a deeply nested data structure that I would like to match on. It contains Vecs internally. I would like something like one of the commented out lines to work:
struct Foo {
bar: Vec<bool>,
}
let foo = Foo {
bar: vec![true, false],
};
match foo {
// Foo{bar:[true,false]} => Ok(()), // expected an array or slice, found Vec<bool>
// Foo{bar:&[true, false]} => Ok(()), // expected struct `Vec`, found reference
// Foo{bar:vec![true,false]} => Ok(()), // Arbitrary expressions aren't allowed in patterns
Foo { bar: v } => match v.as_slice() {
[true, false] => Ok(()),
_ => bail!("match failed!"),
}, // Ugly when nesting deeply
_ => bail!("match failed!"),
}
The match statement can be broken into smaller pieces that first do some dereferencing/unpacking on the value being matched, turning it into a slice first. I am currently doing this in my code, but it is quite ugly, and obscures the structure of the thing being destructured.
The issue is that Vec is in the standard library, not part of the language, but I'm still hoping there is some pattern matching magic that can get around this.
No, pattern-matching vecs (let alone in-place) is not currently supported. Currently, Rust only supports a somewhat limited forms of slice patterns, and even that is fairly recent (1.42).
You could use some of the other Rust facilities to make the code slightly terser but that's about it e.g. if let or matches!
match foo {
Foo { bar: v } if matches!(v.as_slice(), [true, false]) => Ok(()),
_ => bail!("match failed!"),
}
I am trying to create a dictionary of functions with symbols as keys but I am getting an error. I have tried the following:
functions = Dict{
:gauss => (v::Float64)->gauss(v, 0.0, 1.0),
:sin => (v::Float64)-> sin(v),
:nsin => (v::Float64)->(-sin(v)),
:cos => (v::Float64)-> cos(v),
:ncos => (v::Float64)->(-cos(v)),
:tanh => (v::Float64)->tanh(v),
:sigm => (v::Float64)->sigmoid(v),
:id => (v::Float64)->id(v)
}
The error I am getting :
ERROR: LoadError: TypeError: in Type, in parameter, expected Type, got Pair{Symbol,getfield(Main, Symbol("##105#113"))}
Please let me know what I am doing wrong. Thanks for the help in advance.
I figured the{} need to replaced by ().
As you found out your yourself, the {} brackets indicate type parameters whereas the paranthesis indicate a constructor call.
Note, that the ::Float64 type annotations aren't necessary for your functions to be performant. Think of them more as a user interface restriction; that is users won't be able to call your methods with non-Float64s. However, if you want to specify types explicitly, you could also specify the type of your dictionary explicitly as such Dict{Symbol, Function}(...). However, since you don't initialize the Dict empty, Julia will figure out the best type based on your input (symbol function pairs).
Can I retrieve a Method via reflection, somehow combine it with a target object, and return it as something that looks like a function in Scala (i.e. you can call it using parenthesis)? The argument list is variable. It doesn't have to be a "first-class" function (I've updated the question), just a syntactic-looking function call, e.g. f(args).
My attempt so far looks something like this (which technically is pseudo-code, just to avoid cluttering up the post with additional definitions):
class method_ref(o: AnyRef, m: java.lang.reflect.Method) {
def apply(args: Any*): some_return_type = {
var oa: Array[Object] = args.toArray.map { _.asInstanceOf[Object] }
println("calling: " + m.toString + " with: " + oa.length)
m.invoke(o, oa: _*) match {
case x: some_return_type => x;
case u => throw new Exception("unknown result" + u);
}
}
}
With the above I was able to get past the compiler errors, but now I have a run-time exception:
Caused by: java.lang.IllegalArgumentException: argument type mismatch
The example usage is something like:
var f = ... some expression returning method_ref ...;
...
var y = f(x) // looks like a function, doesn't it?
UPDATE
Changing the args:Any* to args:AnyRef* actually fixed my run-time problem, so the above approach (with the fix) works fine for what I was trying to accomplish. I think I ran into a more general issue with varargs here.
Sure. Here's some code I wrote that add an interface to a function. It's not exactly what you want, but I think it can be adapted with few changes. The most difficult change is on invoke, where you'll need to change the invoked method by the one obtained through reflection. Also, you'll have to take care that the received method you are processing is apply. Also, instead of f, you'd use the target object. It should probably look something like this:
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]) = method match {
case m if /* m is apply */ => target.getClass().getMethod("name", /* parameter type */).invoke(target, args: _*)
case _ => /* ??? */
}
Anyway, here's the code:
import java.lang.reflect.{Proxy, InvocationHandler, Method}
class Handler[T, R](f: Function1[T, R])(implicit fm: Manifest[Function1[T, R]]) extends InvocationHandler {
def invoke(proxy: AnyRef, method: Method, args: Array[AnyRef]) = method.invoke(f, args: _*)
def withInterface[I](implicit m: Manifest[I]) = {
require(m <:< manifest[Function1[T, R]] && m.erasure.isInterface)
Proxy.newProxyInstance(m.erasure.getClassLoader(), Array(m.erasure), this).asInstanceOf[I]
}
}
object Handler {
def apply[T, R](f: Function1[T, R])(implicit fm: Manifest[Function1[T, R]]) = new Handler(f)
}
And use it like this:
trait CostFunction extends Function1[String, Int]
Handler { x: String => x.length } withInterface manifest[CostFunction]
The use of "manifest" there helps with syntax. You could write it like this:
Handler({ x: String => x.length }).withInterface[CostFunction] // or
Handler((_: String).length).withInterface[CostFunction]
One could also drop the manifest and use classOf instead with a few changes.
If you're not looking for a generic invoke that takes the method name--but rather, you want to capture a particular method on a particular object--and you don't want to get too deeply into manifests and such, I think the following is a decent solution:
class MethodFunc[T <: AnyRef](o: Object, m: reflect.Method, tc: Class[T]) {
def apply(oa: Any*): T = {
val result = m.invoke(o, oa.map(_.asInstanceOf[AnyRef]): _*)
if (result.getClass == tc) result.asInstanceOf[T]
else throw new IllegalArgumentException("Unexpected result " + result)
}
}
Let's see it in action:
val s = "Hi there, friend"
val m = s.getClass.getMethods.find(m => {
m.getName == "substring" && m.getParameterTypes.length == 2
}).get
val mf = new MethodFunc(s,m,classOf[String])
scala> mf(3,8)
res10: String = there
The tricky part is getting the correct type for the return value. Here it's left up to you to supply it. For example,if you supply classOf[CharSequence] it will fail because it's not the right class. (Manifests are better for this, but you did ask for simple...though I think "simple to use" is generally better than "simple to code the functionality".)