How do you construct "whose name is X" style statements in macruby/scriptingbridge? - macruby

In applescript:
set allItems to every item whose name is "foo"
In rb-appscript:
all_items = items[its.name.eq "Foo"]
Is there a way to construct a similar search/predicate/what-have-you in MacRuby/ScriptingBridge?

Problem: solved!
predicate = NSPredicate.predicateWithFormat %(name = "Foo")
all_items = items.filterUsingPredicate(predicate)
Handy reference.

Related

Kotlin - Find matching objects in array

Let's say I have an array of strings and I want to get a list with objects that match, such as:
var locales=Locale.getAvailableLocales()
val filtered = locales.filter { l-> l.language=="en" }
except, instead of a single value I want to compare it with another list, like:
val lang = listOf("en", "fr", "es")
How do I do that? I'm looking for a one-liner solution without any loops. Thanks!
Like this
var locales = Locale.getAvailableLocales()
val filtered = locales.filter { l -> lang.contains(l.language)}
As pointed out in comments, you can skip naming the parameter to the lambda, and use it keyword to have either of the following:
val filtered1 = locales.filter{ lang.contains(it.language) }
val filtered2 = locales.filter{ it.language in lang }
Just remember to have a suitable data structure for the languages, so that the contains() method has low time complexity like a Set.

How do I overload operators for WPF containers?

type AdderType() =
/// Appends to the container.
static member (+)
(cont:DockPanel,child:#UIElement) =
cont.Children.Add child |> ignore
child
When I make the class like the above and try something like this.
let dock = DockPanel()
let win = Window(Title = "Check the Window Style", Content = dock)
let menu = dock + Menu()
I get the error None of the types 'DockPanel,Menu' support the operator '+'. I was inspired to make the above by Phil Trelford's binding example which goes like this:
type DependencyPropertyValuePair(dp:DependencyProperty,value:obj) =
member this.Property = dp
member this.Value = value
static member (+)
(target:#UIElement,pair:DependencyPropertyValuePair) =
target.SetValue(pair.Property,pair.Value)
target
The above for some reason works. I have no idea why. Would it be possible to overload the + or some other operator so that I could elegantly add controls to containers?
Operators defined inside a class only work if one of the arguments is an instance of the class, but you can define your operator as a global operator:
let (++) (cont:DockPanel) (child:#UIElement) =
cont.Children.Add child |> ignore
child
The following should then work:
let dock = DockPanel()
let win = Window(Title = "Check the Window Style", Content = dock)
let menu = dock ++ Menu()
But to be honest, I don't think this kind of problem is a good place for using custom operators. Using + here is confusing, because you are not really adding two things in any sense. Your operator is not commutative, e.g. (a ++ b) <> (b ++ a).
I think a more idiomatic code would be to define a named function and use the |>:
let appendTo (cont:DockPanel) (child:#UIElement) =
cont.Children.Add child |> ignore
child
let dock = DockPanel()
let win = Window(Title = "Check the Window Style", Content = dock)
let menu = Menu() |> appendTo dock
The way to do it similarly as in the last example would be like this:
type ContainerType(con:Panel) =
member this.Children = con.Children
static member (+)
(child:#UIElement,cont:ContainerType) =
cont.Children.Add child |> ignore
child
let toCon = ContainerType
Actually I do like Tomas's solution better. And Phil Trelford's example looks so much like it is a part of .NET that it slipped my mind that one of the arguments in the static member (+) has DependencyPropertyValuePair as the type which is why the + operator could be overloaded in the first place. So that answers that.

Can I use a string from an array as a selector in Swift?

I am trying to learn Swift -- current task is making a simple menu for a Mac app from an array of objects that contain strings. The problem now is how to pass the selector, which in the array is a string, but in the code is a function.
The class is
class menuArrayObject
{
var title: String = ""
var subMenuTitles: [String] = []
var subMenuSelectors: [String] = []
}
Here is my code
for index2 in 0...counter2 - 1
{
let subMenuTitle = arrayObject.subMenuTitles[index2]
let subMenuSelector = NSSelectorFromString(arrayObject.subMenuSelectors[index2])
let subMenu = NSMenuItem(title: subMenuTitle, action: #selector(subMenuSelector(_:)),keyEquivalent: "")
indexMenu.addItem(subMenu)
}
The error message (on let subMenu =) is: "argument of #selector cannot refer to a property"
Is this do-able? Is this desirable to actually do? Is there a better way?
Thanks in advanceemphasized text
What you are trying to do is totally legit – you can indeed convert a string to a selector, then pass that selector to a menu item.
You're however trying to use the selector literal syntax to initialise a Selector, giving that language construct a Selector as an argument (which is just syntactically wrong), where in fact you can just pass the Selector returned by NSSelectorFromString to the NSMenuItem initialiser call.
The selector literal syntax #selector is used when you have a "fixed" selector in mind that you want to create a Selector for (for instance an instance method of the class you are in). The NSSelectorFromString is intended for this kind of cases like yours where the selector is a variable (now that in Swift 2.2 there is indeed some syntax given for #selector literals!)
import Cocoa
class MenuArrayObject
{
var title: String = "Foo"
var subMenuTitles: [String] = ["foo"]
var subMenuSelectors: [String] = ["foobar"]
}
let menuArrayObject = MenuArrayObject()
let indexMenu = NSMenu()
for (i, submenuTitle) in menuArrayObject.subMenuTitles.enumerate() {
let selectorStr = menuArrayObject.subMenuSelectors[i]
let selector = NSSelectorFromString(selectorStr)
let item = NSMenuItem(title: submenuTitle, action: selector, keyEquivalent: "")
indexMenu.addItem(item)
}

Trouble finding the correct syntax creating vars in objects

Up until now I have been creating var inside the classes I made. e.g.
var backpack:Array = new Array("food", "water");
I want to create objects dynamically now like:
player = {};
player.backpack = ("food", "water"); // not the right syntax
OR
player = {backpack:Array = new Array("food", "water")} // not right either.
Any help? Thanks in advance. I can do this with simple vars like int, but can't find the answer to arrays.
ActionScript's generic object properties don't have any variable type associated with them. You assign them one of the following ways.
Example 1
player = {backpack: new Array("food", "water")};
Example 2
player.backpack = new Array("food", "water");
Example 3
player["backpack"] = new Array("food", "water");
You can use square brackets to define literal arrays. Not only is it shorter, but it's also faster (see this post).
The correct syntax for your two examples are
player = {};
player.backpack = ["food", "water"];
and
player = {backpack: ["food", "water"]};
Also, if you find it easier, you can use it in the first line of code you wrote.
var backpack:Array = ["food", "water"];

Adding items to a multidimensional array without overwriting the old ones?

this may be a simple question, yet I haven't been able to find an answer to it:
How do I add a value to an array without overwriting (all) old values, or having to rewrite them? Is there such a thing as array_push in LUA? And if so, does it work for multidimensional arrays as well?
Example:
Array={"Forest","Beach","Home"} --places
Array["Forest"] = {"Trees","Flowers"} --things you find there
Array["Forest"]["Trees"] = "A tree is a perennial woody plant" --description
If I'd like to add a description of a new thing in a new place, I can't do it using
Array["Restaurant"]["Spoon"] = "A type of cutlery."
because I'd have to declare all these things, as well as the old ones so I don't overwrite them. So I'm looking for something like:
array_push(Array, "Restaurant")
array_push(Array["Restaurant"],"Spoon")
Array["Restaurant"]["Spoon"] = "A type of cutlery."
Thanks!
The following index metamethod implementation should do the trick.
local mt = {}
mt.__index = function(t, k)
local v = {}
setmetatable(v, mt)
rawset(t, k, v)
return v
end
Array={"Forest","Beach","Home"} --places
setmetatable(Array, mt)
Array["Forest"] = {"Trees","Flowers"} --things you find there
Array["Forest"]["Trees"] = "A tree is a perennial woody plant" --description
Array["Restaurant"]["Spoon"] = "A type of cutlery."
Note that you are mixing array indexed values with with string indexed values, and I don't think you intended to do so. For example, your first line stores "Forest" under the key "1", while the second line creates a new table key "Forest" with a table value that holds sequential string values. The following code prints out the generated structure to demonstrate my meaning.
local function printtree(node, depth)
local depth = depth or 0
if "table" == type(node) then
for k, v in pairs(node) do
print(string.rep('\t', depth)..k)
printtree(v, depth + 1)
end
else
print(string.rep('\t', depth)..node)
end
end
printtree(Array)
Next is the resulting output of the two code snippets listed above.
1
Forest
2
Beach
3
Home
Restaurant
Spoon
A type of cutlery.
Forest
1
Trees
2
Flowers
Trees
A tree is a perennial woody plant
With this understanding, you could then solve your problem without such trickery as follows.
Array = {
Forest = {},
Beach = {},
Home = {}
}
Array["Forest"] = {
Trees = "",
Flowers = "",
}
Array["Forest"]["Trees"] = "A tree is a perennial woody plant"
Array["Restaurant"] = {
Spoon = "A type of cutlery."
}
printtree(Array)
The output is then what you probably expected.
Restaurant
Spoon
A type of cutlery.
Beach
Home
Forest
Flowers
Trees
A tree is a perennial woody plant
With all of that in mind, the following accomplishes the same thing, but is much clearer in my humble opinion.
Array.Forest = {}
Array.Beach = {}
Array.Home = {}
Array.Forest.Trees = ""
Array.Forest.Flowers = ""
Array.Forest.Trees = "A tree is a perennial woody plant"
Array.Restaurant = {}
Array.Restaurant.Spoon = "A type of cutlery."
printtree(Array)
First, what you're making is not an array at all, but a dictionary. Try:
T = { Forest = { } , Beach = { } , Home = { } }
T.Forest.Spoon = "A type of cutlery"
Otherwise table.insert may be what you want in array_push
This is almost identically there in standard Lua like this:
Array.Restaurant={}
Array.Restaurant.Spoon={}
Array.Restaurant.Spoon[1]="A type of cutlery."
the table.key notation is equivalent of the table["key"] notation.
Now every item has it's description in the value corresponding to a number-key, and sub items as values corresponding to string keys.
If you really want to have exactly the same syntax as your example, you'll have to use metatables (__index and __newindex methods).

Resources