First time here? Check out the FAQ!

Test using an array of values instead of several \/ (Logical OR) values?

0 votes
I have a working way to trigger when a value equals a particular set of numbers based upon Capytalk Logical OR.

(currentRowNumber eq: 10) \/
(currentRowNumber eq: 50) \/
(currentRowNumber eq: 100)

so when acting as a gate the number 10, 50, or 100 will trigger my sound.

I am wondering about doing a similar check but using an array of test values #(10 50 100) instead of a bunch of \/ OR tests.

for example, something like this.

currentRowNumber eq: (1 to: 4 do: [:i |
  (#(10 20 50 100) at: i) ])

Probably similar computationally(?) but I cannot get this method to work. Any hints?
asked Sep 1, 2022 in Capytalk & Smalltalk by jonbellona (Adept) (1,300 points)

1 Answer

+1 vote

Hi Jon, 

This looks like a job for inject:into: which you can use to construct the compound OR statement. 

You could do something like this

| init values currentRowNumber |

currentRowNumber := !value.
values := #(10 20 30 40 50 60).
init := currentRowNumber eq: (values at: 1).
(2 to: values size) inject: init into: [:expr :i |
    expr \/ (currentRowNumber eq: (values at: i))


Which evaluates to:

 (!Value eq: 10) \/ (!Value eq: 20) \/ (!Value eq: 30) \/ (!Value eq: 40) \/ (!Value eq: 50) \/ (!Value eq: 60)



answered Sep 1, 2022 by alan-jackson (Virtuoso) (15,840 points)
Works! Thank you.

Wow. I feel like I just leveled up. So I understand the logic of the Smalltalk here,
"init" is the starting expression that passes not just the starting value but also the variables in scope down to the loop?
"expr" is the expression thus far, which is why the loop starts at index 2 instead of 1?

I miss Kyma Kata. Thanks for answering my question.
Yes, sort of.

What's important to remember is that Smalltalk only runs once at compile time, but Capytalk expressions, like dogs, are for life not just for compilemas. So here we're using the power of Smalltalk to build a Capytalk expression. As it's the last thing the Smalltalk does, that Capytalk expression is left on the stack and that's the thing that's spouted off to the paca*.

Anything with square brackets, [], or := is Smalltalk.

In this example we don't really need the init variable, we could use the expression directly as an argument for the inject:into: message -  

    (2 to: values size) inject: (currentRowNumber eq: (values at: 1)) into: [:expr :i |...

- I just think it reads slightly easier putting the expression in a variable first.
Another way to construct the Capytalk expression:

#(10 20 50 100) inject: 0 into: [ :expr :value | expr \/ (!currentRowNumber eq: value)].

The Capytalk expression generated by the Smalltalk inject:into: will be:

((0 \/ (!currentRow eq: 10)) \/ (!currentRow eq: 20)) \/ ...
Thanks Alan!
Thank you SSC!
Using an array of the values as the receiver of inject:into: is so much tidier! I sometimes forget how cute Smalltalk can be.