Adding collections from different instances - collections

I am new to Smalltalk and I am trying to do a very simple program that would produce a single collection, out of multiple collections in this way:
Let's say I have a Set of Armories, and every Armory has it's own Weapons Set, what I would like to do is to write a method that would return a single collection with all the Weapons from every Armory combined.
Thanks in advance for your help!

Try something like this:
armories inject: OrderedCollection new into: [:collection :armory |
collection addAll: armory weapons; yourself].

I'd like to improve David's answer by proposing this solution:
armories inject: OrderedCollection new into: [:allWeapons :armory |
allWeapons, armory weapons]
As , returns concatenation of 2 collections.
Now also there is sort of more "fluid" way without creation of new OrderedCollection. There is a method called fold: or reduce: or 'reduceLeft:` which is a concept from functional programming. So you can do:
(armories collect: #weapons) fold: [allWeapons :weapons |
allWeapons, weapons]
So armories collect: #weapons will give you a collections of collections of weapons. fold: takes 1st element and 2nd and executes the block on them. Then in take a result and a 3rd element, and so on…
Now the best solution that I know is flatCollect:. I'm sure that it's present in pharo, but may be missing from other smalltalk based languages. This is the same as collect: but flattens the result one level. So all you have to do is:
armories flatCollect: #weapons
Enjoy

David's answer is the classic smalltalk idiom. When doing more complex combinations you might prefer a stream based approach:
OrderedCollection fromStream: [:allWeapons |
allWeapons nextPutAll: armories collect: [:armory | armory weapons]]

Related

Iterate over a map in Rascal

I'm trying to create a map comprehension over a map in this structure:
map[Node, set[Node]]
And my map comprehension is something like:
(currentNode: {currentNode} | <currentNode, _> <- dominanceSet);
But I'm getting this error:
Is there a way to achieve a similar behaviour using another strategy?
The generator for maps in Rascal produces the key values (and not some form of "entries" or tuples).
So the code would be:
(currentNode: {currentNode} | currentNode <- dominanceSet)
Note that there are some specialized functions in the standard library for faster indexing relations, like in Relations there is map[&K, set[&V]] index(rel[&K, &V] R);

Creating a specific list in Prolog

I want to write a function to write a list that, for example, for the code below
likes('john', 'soccer')
likes('mary', 'football')
likes('eric', 'soccer')
So the function I want to write would be like
whoLikes('soccer', list)
And the list would be ('john', 'eric')
Should I use recursion to do this? How?
Use can use the built-in predicate setof/3:
likes(messi,soccer).
likes(ronaldo,soccer).
likes(jordan,basketball).
whoLikesSoccer(F):- setof(X,likes(X,soccer),F).
OUTPUT
?- whoLikesSoccer(X).
X=[messi,ronaldo].
false

Prolog - How can I save results from recursive calls?

I am still trying to understand the Prolog logic and have stumbled upon a problem.
I am trying to save values found within recursive calls, to pass on or gather.
As such:
main([]) :- !.
main([H|Tail]) :- findall(X,something(_,_,X),R),
getValueReturn(R,H,Lin, Lout),
main(Tail).
% X is the Head from main
getValueReturn([H|Tail],X,Lin, Lout) :- subset(X, H) ->
findall(A,something(A,_,H),L1),
append(Lin,L1,Lout),
getValueReturn(Tail,X,Lout,L)
;
getValueReturn(Tail,X,Lin,Lout).
I would like to gather the results from findall in getValueReturn, combine them, and send them back to main, which can then use them.
How do I create and add to a list within getValueReturn?
Similarly, how can I save the list in my main for all recursive calls?
EDIT:
I edited the code above as per a comment reply, however when I run this through trace, the list deletes all elements when the empty list is found.
What am I doing wrong? This is the first time I try to use the concept of building a list through recursion.
You should post complete code that can be run, with example data. I have not tested this.
You need to pass L around on the top-level also. Using the same variable names for different parameters in adjacent procedures does not improve readability.
main([E|Es],L0,L) :-
findall(X,something(_,_,X),Rs),
getValueReturn(Rs,E,L0,L1),
main(Es,L1,L).
main([],L,L).
getValueReturn([R|Rs],E,L0,L) :-
( subset(E,R) ->
findall(A,something(A,_,R),New),
append(L0,New,L1),
getValueReturn(Rs,E,L1,L)
; getValueReturn(Rs,E,L0,L) ).
getValueReturn([],_,L,L).
A variable can only have one value in Prolog. In your code, for example, Lout is the output from append/3, an input to a recursive call of getValueReturn/4, and then also the output on the top-level. This is probably not going to do what you want.
I have found the best way to do what I was trying to was to use asserta/z when a result was found, and then gather these results later on.
Otherwise the code became overly complicated and did not function as intended.

How to create a collection in Julia?

This seems like a really basic question, but can't find the answer. How do I create a collection in Julia? For example, I want to open a text file and parse each line to create an (iterable or otherwise) collection. Obviously I don't know how many elements there are in advance.
I can iterate through the lines like this
I = each_line(open(fileName,"r"))
state = start(I)
while !done(I, state)
(i, state) = next(I, state)
println(i)
end
But I don't know how to put each i into an array or other collection. I tried
map( i -> println(i), each_line(open(fileName,"r") ) )
But got the error
no method map(Function,EachLine)
You could do this:
lines = String[]
for line in each_line(open(fileName))
push!(lines, line)
end
And then lines contains the list of lines. You need the String in the first line to make the array extensible.
Standard collections and supported operations are mainly covered in the standard library documentation.
Specifically, the Deques section covers all of the operations supported by the 1d Array type (vector), including push! and pop! as well as insertion, resizing, etc.
Omar's answer is correct, and I will just add a small qualification: String[] creates a 1d array of Strings. The same constructor syntax may be used for example to create Int[], Float[], or even Any[] vectors. The latter type may hold objects of any type.
Depending on your Julia version, you may also be able to write collect(eachline(open("LICENSE.md"))) or [eachline(open("LICENSE.md"))...]. I think these won't work in 0.1.x versions but will working in newer 0.2 development versions (which are recommended at this point – 0.2 is on its way soon).

Is there a nice idiom for adding a new list or appending to a list (if present) in a dictionary?

This is the second time I've implemented something like this and I suspect there has to be a better (read: more pythonic) way to do this:
phone_book = {}
def add_number(name,number):
if name in phone_book:
phone_book['name'].append(number)
else:
phone_book['name'] = [number]
I realize the code can likely be made more concise with conditional assignments, but I suspect there's likely a better way to go about this. I'm not interested in only making the code shorter.
Yep, you can use defaultdict. With this dict subclass, when you access an element in the dictionary, if a value doesn't already exist, it automatically creates one using a constructor function you specify.
from collections import defaultdict
phone_book = defaultdict(list)
def add_number(name, number):
phone_book[name].append(number)
Use dict's setdefault like this:
phone_book.setdefault('name', []).append(number)

Resources