What is the at ("#") operator in Pharo? - pharo

I've looked online for a meaning of the # operator in Pharo, but couldn't find anything.
What's the meaning of the Pharo # operator? For instance, why does 25#50 get evaluated as: "(25#50)"?

In Smalltalk, the # symbol is used to create instances of the class Point. An instance of such a class has two ivars x and y. You can create a Point using the x:y: message, like this
Point x: 3 y: 4.
However, it is less verbose to use the message # like this
3 # 4
to create the same thing.
Note that while x:y: is a message you send to the class Point, the message # 4 is sent to the integer 3. In other words, the former is a class message, the latter an instance message.
Note that, since many people write 3#4 instead of 3 # 4, this has the risk of creating a surprising side effect. In fact
3#-4
should be (in principle) the Point with coordinates 3 and -4. However, the Smalltalk syntax is different and will parse it as the message with selector #- and argument 4 sent to the receiver 3. This is why some dialects make an exception so that the message is interpreted as 3 # -4, which can be achieved by implementing the method #- in Number or by tweaking the parser.

In Pharo it is a method defined in the Number class
# y
"Primitive. Answer a Point whose x value is the receiver and whose y
value is the argument. Optional. No Lookup. See Object documentation
whatIsAPrimitive."
<primitive: 18>
^Point x: self y: y

Related

Generating Solution Candidates For Matching People in Clingo/ASP

I have a list of people and I want to pair them all then do some filtering based on preferences. When I generate my candidate solutions, how do I avoid creating candidate solutions that re-pair a people.
For example:
person(a;b;c;d) .
{match(X, Y): person(Y)}1 :- person(X) .
This generates candidate solutions that include match(a,b) match(c,b) ...
I would like ONLY candidate solutions that do not rematch anyone like: match(a,b) match(c,d) ...
My goal is to not have to filter rematches out via additional constraints. Also, not everyone needs to be matched. Thanks!
person(a;b;c;d).
{match(A,B) : person(A), person(B), A < B}.
:- person(A), 1 < {match(A,B); match(B,A)}.
You exclude solutions that have more than 1 match for a single person.
It is not possible to simply choose a correct set of atoms without additional constraints. As match(a,b) and match(b,c) can occur in different answer sets, both variables need to be created. Only a constraint can rule out that both do not occur in the same answer set.
Also note that your generator rule
{match(X, Y): person(Y)}1 :- person(X) .
already is a shortcut writing for
{match(X, Y): person(Y)} :- person(X).
:- person(X), 2 {match(X, Y): person(Y)}.
And therefore you are already using a constraint whenever your generator choice rule has non-trivial bounds.
PS: Check the different versions using --stats=2 for constraint count and --text for a rough approximation of what kind of constraints are generated.
I'd go for Max Ostrowskis answer.
One of the difficulties is to handle the order of the attributes for the match predicate: this is a tuple, there is a difference if your value shows up on first or second position. Adding a rule to make the predicate commutative should do the trick since you don't need to distinguish for a value to be on first or second position. This method does not use a constraint (on first sight), but it duplicates the generated values so the output differs from your desired solution. Also it adds a line to the code.
person(a;b;c;d).
{match(X,Y): person(Y), X!=Y}1 :- person(X).
match(Y,X) :- match(X,Y).
#show match/2.
Output
Answer: 1
Answer: 2
match(c,a) match(a,c)
Answer: 3
match(b,a) match(a,b)
Answer: 4
match(c,d) match(d,c)
Answer: 5
match(b,a) match(a,b) match(c,d) match(d,c)
Answer: 6
match(b,d) match(d,b)
Answer: 7
match(c,a) match(a,c) match(b,d) match(d,b)
Answer: 8
match(b,c) match(c,b)
Answer: 9
match(d,a) match(a,d)
Answer: 10
match(d,a) match(a,d) match(b,c) match(c,b)
SATISFIABLE

What to do when a code review tool declares unmatched types?

I am working on developing a large-scale Python (backend) project. I was working with a firm that does extensive testing, and they built the frontend and test tools. Before every deploy, all the tools (like linters) are run regularly.
I had put down the code for a while, and now it fails many tests. Some of these are deprecation warnings for features or syntax soon to be deprecated, and they note they started classifying those as warnings (to later become errors) starting January 1, 2020, so I know they make dynamic changes in the tools themselves.
My problem is a bunch of code that used to pass no longer does. And the error is always the same: if I have a line that looks like so, I get an error that says something along the lines of "error: may not use operator '-' with incompatible types; a and b are of types numpy.array and NoneType":
x = a - b
This gets fixed by making the code super-messy with this sort of fix:
x = a.astype(float) - b.astype(float)
It's even worse because in the actual code there are 3 variables, all doing addition and subtraction with a 'c' that is an integer array kicking around along with the two numpy arrays. But then the code goes from:
x = a - b - c
to:
x = a.astype(float) - b.astype(float) - c.astype(float)
And this won't work since int's don't have an astype method. The error looks like this now:
File "/home/engine.py", line 165, in Foo
lower_array[t].astype(float)) / num_values.astype(float)
AttributeError: 'NoneType' object has no attribute 'astype'
Thus, I end up with:
x = a.astype(float) - b.astype(float) - float(c)
This is all extraordinarily cumbersome and nasty casting that is required, and makes the code impossible to read.
The odd thing to me is that all three arrays were instantiated as numpy arrays, i.e.,:
a=numpy.array(_a)
b=numpy.array(_b)
c=numpy.array(_c)
When I ask the code to put output to stdout the type of all three vars, they all say . Yet, the next line of code blows up and dumps, saying "Attribute error: 'NoneType' object has no attribute 'astype'"
I can't fathom how a static code analyzer determines the types - other than as numpy.ndarray type - since Python uses duck-typing. Thus, the type could change dynamically. But that's not the case here; all three vars are identified as numpy.ndarray type, but "z = a - b - c" fails.
Anyone understand what's going on here?
After much work, the answer is to ignore the linter. Readable code is the object, not code that satisfies a linter.

Remove single quotes/quotation marks in Prolog

I have an extern API sending info to my Prolog application and I found a problem creating my facts.
When the information received is extensive, Prolog automatically adds ' (single quotes) to that info.
Example: with the data received, the fact I create is:
object(ObjectID,ObjectName,'[(1,09:00,12:00),(2,10:00,12:00)]',anotherID)
The fact I would like to create is
object(ObjectID,ObjectName,[(1,09:00,12:00),(2,10:00,12:00)] ,anotherID)
without the ' before the list.
Does anyone know how to solve this problem? With a predicate that receives '[(1,09:00,12:00),(2,10:00,12:00)]' and returns [(1,09:00,12:00),(2,10:00,12:00)]?
What you see is an atom, and you want to convert it to a term I think.
If you use swi-prolog, you can use the builtin term_to_atom/2:
True if Atom describes a term that unifies with Term. When Atom is instantiated, Atom is parsed and the result unified with Term.
Example:
?- term_to_atom(X,'[(1,09:00,12:00),(2,10:00,12:00)]').
X = [ (1, 9:0, 12:0), (2, 10:0, 12:0)].
So at the right hand side, you enter the atom, at the left side the "equivalent" term. Mind however that for instance 00 is interpreted as a number and thus is equal to 0, this can be unintended behavior.
You can thus translate the predicate as:
translate(object(A,B,C,D),object(A,B,CT,D)) :-
term_to_atom(CT,C).
Since you do not fully specify how you get this data, it is unknown to me how you will convert it. But the above way will probably be of some help.

How to use IN with a block instead of an object?

The IN function in Rebol finds out if a field is in an object:
USAGE:
IN object word
DESCRIPTION:
Returns the word or block in the object's context.
IN is a native value.
ARGUMENTS:
object (any-object! block!)
word -- (modified if series) (any-word! block! paren!)
The claim is it works with objects or blocks. It works okay if I try it with an object:
>> in object [foo: 10 bar: 20] 'foo
== foo
But if I just try it with a raw block, it gives back NONE:
>> in [foo: 10 bar: 20] 'foo
== none
Guess I'd understand if it didn't support blocks (Rebol2 didn't). But what's the case in which it wouldn't return NONE that blocks are allowed for?
And at the risk of making this two questions in one, what's the deal with accepting BLOCK! for the word parameter? I'd think it would take a block if you had a set of words you were looking for, but it seems to just return the block:
>> in object [foo: 10 bar: 20] [mumble frotz bar]
== [mumble frotz bar]
>> in object [foo: 10 bar: 20] [mumble frotz]
== [mumble frotz]
And at the further risk of making this three questions, what meaning would taking a PAREN! for word have?
The IN function isn't primarily meant for searching an object for a word, it is for returning a word or block of words that are in the object, or in Rebol terms bound to the object. It's a variant of the BIND function that is useful in different circumstances than BIND.
If there is no word of that name in the object, it returns none, sensibly enough. This gives it the side benefit of being able to be used in conditional expressions as a word detection function, but that's not its main use.
IN can take a block of objects for its object parameter and then try to bind the word to each object in turn, returning a word bound to the first object in the block that has that word. This was meant as a relatively quick way to do overriding word lookup for an old design of the Rebol 3 GUI, but it turned out to not be the best approach in that case so the GUI doesn't use that design now. However, IN block word was kept as a potentially useful feature for future use elsewhere.
In your example, there were no objects in that block, so there was nothing that IN could bind the word to. That is why IN returned none.
If you pass IN a block for the word parameter, it binds the block to the object before it returns it. This is to allow code like do in obj [print a]. It doesn't do a bind/copy though, so you should be careful about code like that. Or maybe IN object block should copy - is it too late to change that? Passing a paren for the word argument should have the same binding behavior as passing a block.
When last I checked, we didn't support having both the object an word parameters be blocks. This is because we couldn't figure out a good model for what that behavior should be, at least obviously. The overriding word lookup doesn't really work with a block of words because the results would be inconclusive.
It would be useful to have a function that rebound a block to a series of objects in order, especially for recreating Rebol's not-really-nested scopes, but it would be really confusing for that function to be IN.
This might not be as useful, but since it is not explicitly mentioned, and I think is the 'right' way to solve your first question for now:
red>> first find [foo: 10 bar: 20] 'foo
== foo:
This doesn't work on rebol2 tho, but quoteing the set-word! does :
>> first find [foo: 10 bar: 20] quote [foo:]
== foo:
Still has the slight disadvantage of returning a set-word!

groovy list spreading

If you run the following Groovy code, the assertion passes
def foo(a, b) {
a + b
}
assert 'aaabbb' == foo(['aaa', 'bbb'])
This suggests that if a method is called with a List parameter that contains X elements, then the List will be spread and a method with X arguments will be invoked.
Of course, this will only happen if there isn't a method defined with a single parameter of type List (or ancestor thereof).
I only discovered this quite recently when reading another SO Groovy answer. I've never seen it mentioned in the Groovy docs, release notes, or books. Is it a hidden feature, a bug, or just something I've missed?
Going to be removed in Groovy 2 apparently:
http://groovy.329449.n5.nabble.com/removing-features-in-Groovy-2-td4422494.html
JT's first on the to-remove list and it seems everyone (with clout) on Groovy User agrees.

Resources